Я пытаюсь понять разницу между ng-if
и ng-show
/ ng-hide
, но они выглядят одинаково для меня.
Есть ли разница, которую я должен иметь в виду, выбирая один или другой?
Я пытаюсь понять разницу между ng-if
и ng-show
/ ng-hide
, но они выглядят одинаково для меня.
Есть ли разница, которую я должен иметь в виду, выбирая один или другой?
Ответы:
В ngIf
директиве удаляет или воссоздает часть дерева DOM на основе выражения. Если выражение, назначенное для, ngIf
оценивается как ложное значение, то элемент удаляется из DOM, в противном случае клон элемента повторно вставляется в DOM.
<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>
<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>
Когда элемент удаляется с использованием ngIf
его области действия, при восстановлении элемента создается новая область. Область, созданная внутри, ngIf
наследуется от родительской области с использованием наследования прототипа.
Если ngModel
используется внутри ngIf
для привязки к примитиву JavaScript, определенному в родительской области, любые изменения, внесенные в переменную в дочерней области, не влияют на значение в родительской области, например
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="data">
</div>
Чтобы обойти эту ситуацию и обновить модель в родительской области из дочерней области, используйте объект:
<input type="text" ng-model="data.input">
<div ng-if="true">
<input type="text" ng-model="data.input">
</div>
Или $parent
переменная для ссылки на родительский объект области:
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="$parent.data">
</div>
В ngShow
директиве показывает или скрывает данный HTML элемент на основе выражения , предоставленное ngShow
атрибут. Элемент отображается или скрывается путем удаления или добавления ng-hide
класса CSS на элемент. Класс .ng-hide
CSS предопределен в AngularJS и устанавливает стиль отображения равным none (с использованием !important
флага).
<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>
<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>
Когда ngShow
выражение вычисляется до false
этого, ng-hide
класс CSS добавляется к class
атрибуту элемента, что делает его скрытым. Когда true
, то ng-hide
класс CSS удаляются из элемента вызывает элемент не появляться скрыто.
data.input
он работает ... но data
один в модели не работает. @CodeHater
ngIf
создает новую область, поэтому, глядя на приведенный выше пример, ngModel
можно создать новую data
модель, даже если в родительской области существует модель с тем же именем. Но когда вы используете точечную запись, вы заставляете JS искать цепочку прототипов области. Поэтому, если он не найдет значение в текущей области, он попытается найти его в родительской области и так далее. Немногие другие директивы , которые создают различные сферы являются ngInclude
, ngRepeat
. Надеюсь, теперь все ясно. :)
Может быть, интересный момент, это разница между приоритетами между ними.
Насколько я могу судить, директива ng-if имеет один из самых высоких (если не самый высокий) приоритет среди всех угловых директив. Это означает: он будет запускаться ПЕРВЫМ раньше всех других директив с более низким приоритетом. Тот факт, что он запускается FIRST, означает, что по сути элемент удаляется до обработки любых внутренних директив. Или, по крайней мере: вот что я делаю из этого.
Я наблюдал и использовал это в пользовательском интерфейсе, который я создаю для своего текущего клиента. Весь пользовательский интерфейс довольно плотно упакован, и в нем есть ng-show и ng-hide. Не вдаваясь в подробности, но я создал общий компонент, которым можно управлять с помощью конфигурации JSON, поэтому мне пришлось переключиться внутри шаблона. Присутствует ng-repeat, а внутри ng-repeat показана таблица, в которой присутствует множество ng-show, ng-hides и даже ng-switch. Они хотели показать по крайней мере 50 повторов в списке, что привело бы к разрешению более или менее 1500-2000 директив. Я проверил код, и для обработки данных бэкэнд Java + пользовательский JS на передней панели заняли бы около 150 мс, а затем Angular потратил на это 2-3 секунды перед отображением. Заказчик не жаловался, но я был в шоке :-)
В своем поиске я наткнулся на директиву ng-if. Теперь, может быть, лучше указать, что на момент создания этого интерфейса не было доступно ng-if. Поскольку в ng-show и ng-hide были функции, которые возвращали логические значения, я мог легко заменить их все на ng-if. При этом все внутренние директивы, казалось, больше не оценивались. Это означало, что я сократил примерно треть всех оцениваемых директив, и, таким образом, пользовательский интерфейс ускорился примерно до 500 мс - время загрузки 1 с. (У меня нет возможности определить точные секунды)
Обратите внимание: тот факт, что директивы не оценены, является обоснованным предположением о том, что происходит под ними.
Итак, на мой взгляд: если вам нужно, чтобы элемент присутствовал на странице (то есть: для проверки элемента или чего-либо еще), но просто был скрыт, используйте ng-show / ng-hide. Во всех остальных случаях используйте ng-if.
ng-if
Директива удаляет содержание страницы и ng-show/ng-hide
использует CSS display
свойство содержания скрыть.
Это полезно в случае , если вы хотите использовать :first-child
и :last-child
псевдо - селекторы стиля.
:first-child
и :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@EdSpencer правильно. Если у вас много элементов и вы используете ng-if только для создания экземпляров соответствующих элементов, вы экономите ресурсы. @CodeHater также несколько корректен, если вы собираетесь удалять и показывать элемент очень часто, то его скрытие вместо удаления может повысить производительность.
Основной вариант использования, который я нахожу для ng-if, заключается в том, что он позволяет мне чисто проверять и исключать элемент, если его содержимое недопустимо. Например, я мог бы сослаться на переменную с нулевым именем изображения, и это вызовет ошибку, но если я ng-if и проверим, является ли оно нулевым, это все хорошо. Если бы я сделал ng-show, ошибка все равно бы сработала.
В отношении ng-if и ng-show следует отметить одну важную вещь: при использовании элементов управления формой их лучше использовать, ng-if
поскольку они полностью удаляют элемент из dom.
Это различие важно, потому что если вы создадите поле ввода с помощью, required="true"
а затем настроите ng-show="false"
его скрыть, Chrome выдаст следующую ошибку, когда пользователь попытается отправить форму:
An invalid form control with name='' is not focusable.
Причина в том, что поле ввода присутствует, required
но оно скрыто, поэтому Chrome не может сосредоточиться на нем. Это может буквально нарушить ваш код, так как эта ошибка останавливает выполнение скрипта. Так что будь осторожен!
@Gajus Kuizinas и @CodeHater верны. Здесь я просто привожу пример. Пока мы работаем с ng-if, если присвоенное значение равно false, то все элементы html будут удалены из DOM. и если присвоенное значение равно true, то элементы HTML будут видны в DOM. И область будет отличаться по сравнению с родительской областью. Но в случае ng-show он просто покажет и скроет элементы на основе назначенного значения. Но это всегда остается в DOM. Только видимость изменяется согласно назначенному значению.
http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview
Надеюсь, этот пример поможет вам понять сферу применения. Попробуйте задать ложные значения для ng-show и ng-if и проверьте DOM в консоли. Попробуйте ввести значения в поля ввода и обратите внимание на разницу.
<!DOCTYPE html>
<input type="text" ng-model="data">
<div ng-show="true">
<br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
<br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div>
{{data}}
Тот факт, что эта ng-if
директива, в отличие от этого ng-show
, создает собственную область применения, приводит к интересному практическому различию:
angular.module('app', []).controller('ctrl', function($scope){
$scope.delete = function(array, item){
array.splice(array.indexOf(item), 1);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='ctrl'>
<h4>ng-if:</h4>
<ul ng-init='arr1 = [1,2,3]'>
<li ng-repeat='x in arr1'>
{{show}}
<button ng-if='!show' ng-click='show=!show'>Delete {{show}}</button>
<button ng-if='show' ng-click='delete(arr1, x)'>Yes {{show}}</button>
<button ng-if='show' ng-click='show=!show'>No</button>
</li>
</ul>
<h4>ng-show:</h4>
<ul ng-init='arr2 = [1,2,3]'>
<li ng-repeat='x in arr2'>
{{show}}
<button ng-show='!show' ng-click='show=!show'>Delete {{show}}</button>
<button ng-show='show' ng-click='delete(arr2, x)'>Yes {{show}}</button>
<button ng-show='show' ng-click='show=!show'>No</button>
</li>
</ul>
<h4>ng-if with $parent:</h4>
<ul ng-init='arr3 = [1,2,3]'>
<li ng-repeat='item in arr3'>
{{show}}
<button ng-if='!show' ng-click='$parent.show=!$parent.show'>Delete {{$parent.show}}</button>
<button ng-if='show' ng-click='delete(arr3, x)'>Yes {{$parent.show}}</button>
<button ng-if='show' ng-click='$parent.show=!$parent.show'>No</button>
</li>
</ul>
</div>
В первом списке on-click
событие, show
переменная из внутренней / внутренней области видоизменения изменяется, но отслеживаетng-if
другую переменную из внешней области с таким же именем, поэтому решение не работает. В случае, если у ng-show
нас есть только одна show
переменная, поэтому она работает. Чтобы исправить первую попытку, мы должны обратиться к show
родительской / внешней области видимости через $parent.show
.
ng-if, если false, удалит элементы из DOM. Это означает, что все ваши события, директивы, связанные с этими элементами, будут потеряны. Например, если щелкнуть по ng одним из дочерних элементов, когда ng-if оценивается как false, этот элемент будет удален из DOM, а когда он верен, он будет воссоздан.
ng-show / ng-hide не удаляет элементы из DOM. Он использует стили CSS (.ng-hide), чтобы скрывать / показывать элементы. Таким образом, ваши события, директивы, которые были прикреплены к дочерним элементам, не будут потеряны.
ng-if создает дочернюю область, а ng-show / ng-hide - нет.
ng-show и ng-hide работают противоположным образом. Но разница между ng-hide или ng-show с помощью ng-if заключается в том, что если мы используем ng-if, то элемент будет создан в dom, но с элементом ng-hide / ng-show будет полностью скрыт.
ng-show=true/ng-hide=false:
Element will be displayed
ng-show=false/ng-hide=true:
element will be hidden
ng-if =true
element will be created
ng-if= false
element will be created in the dom.
Отметим, что со мной сейчас произошло нечто: ng-show скрывает содержимое через css, да, но это приводило к странным сбоям в элементах div, которые должны быть кнопками.
У меня была карточка с двумя кнопками внизу, и в зависимости от фактического состояния одна заменяется третьей, например, кнопка редактирования с новой записью. Используя ng-show = false, чтобы скрыть левый (присутствует первым в файле), получилось, что следующая кнопка оказалась с правой границей вне карты. ng-if исправляет это, вообще не включая код. (Только что здесь проверено, есть ли скрытые сюрпризы, используя ng-if вместо ng-show)
ngIf выполняет манипуляции с DOM, удаляя или воссоздавая элемент.
Принимая во внимание, что ngShow применяет правила CSS для скрытия / показа вещей.
Для большинства случаев (не всегда) я бы суммировал это следующим образом: если вам нужна одноразовая проверка, чтобы показать / скрыть объекты, используйте ng-if
, если вам нужно показать / скрыть объекты, основываясь на действиях пользователя на экране (например, флажок установите флажок, затем отобразите текстовое поле, снимите флажок, затем скрыть текстовое поле и т. д.), затем используйтеng-show
Одно интересное отличие в ng-if и ng-show:
БЕЗОПАСНОСТЬ
Элементы DOM, присутствующие в блоке ng-if, не будут отображаться, если его значение равно false
где, как и в случае ng-show, пользователь может открыть окно проверки элемента и установить для него значение TRUE.
И с криком, все содержимое, которое должно было быть скрыто, отображается, что является брешей в безопасности. :)
ng-if
добавленной модельюng-model
, больше не существует.