Я пытаюсь понять разницу между 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 в элемент. Класс CSS .ng-hide
предопределен в 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 удаляется из элемента, заставляя элемент не казаться скрытым.
Возможно, интересный момент - разница между приоритетами между ними.
Насколько я могу судить, директива ng-if имеет один из самых высоких (если не самый высокий) приоритет всех директив Angular. Это означает: он будет запускать FIRST перед всеми другими директивами с более низким приоритетом. Тот факт, что он запускает FIRST, означает, что элемент эффективно удаляется до того, как будут обработаны все внутренние. Или, по крайней мере: это то, что я делаю.
Я наблюдал и использовал это в пользовательском интерфейсе, который я создаю для своего текущего клиента. Весь пользовательский интерфейс довольно сильно упакован, и на нем было ng-show и ng-hide. Не вдаваться в подробности, но я создал общий компонент, которым можно было управлять с помощью конфигурации JSON, поэтому мне пришлось сделать некоторые изменения внутри шаблона. Существует ng-repeat present, а внутри ng-repeat показана таблица, в которой много ng-show, ng-hides и даже ng-переключателей. Они хотели показать не менее 50 повторов в списке, что приведет к тому, что более или менее 1500-2000 директив будут разрешены. Я проверил код, а бэкэнд Java + пользовательский JS на передней панели занял около 150 мс для обработки данных, а затем Angular пережевал бы около 2-3 секунд, прежде чем отображать. Клиент не жаловался, но я был потрясен:-)
В моем поиске я наткнулся на директиву ng-if. Теперь, может быть, лучше всего указать на то, что при понимании этого пользовательского интерфейса не было ng-если оно доступно. Поскольку 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
для стиля.
@EdSpencer верен. Если у вас много элементов, и вы используете ng - если вы только создаете экземпляр соответствующих, вы сохраняете ресурсы. @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 не может сфокусироваться на нем. Это может буквально разорвать ваш код, так как эта ошибка останавливает выполнение script. Будьте осторожны!
@Gajus Kuizinas и @CodeHater верны. Здесь я просто приведу пример. Пока мы работаем с ng-if, если назначенное значение ложно, то все элементы html будут удалены из DOM. и если назначенное значение истинно, то элементы 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>
ng - если false приведет к удалению элементов из DOM. Это означает, что все ваши события, директивы, привязанные к этим элементам, будут потеряны. Например, ng-click для одного из дочерних элементов, когда ng-if оценивает значение false, этот элемент будет удален из DOM и снова, когда он верен, он воссоздается.
ng-show/ng-hide не удаляет элементы из DOM. Он использует стили CSS (.ng-hide), чтобы скрыть/показать элементы. Таким образом ваши события, директивы, прикрепленные к детям, не будут потеряны.
ng-if создает дочернюю область, пока ng-show/ng-hide не делает.
Чтобы заметить, что случилось со мной сейчас: ng-show действительно скрывает содержимое через css, да, но это привело к странным сбоям в div, которые должны быть кнопками.
У меня была карта с двумя кнопками внизу и в зависимости от фактического состояния, которое обменивается с третьей кнопкой редактирования примера с новой записью. Используя ng-show = false, чтобы скрыть левый (присутствующий сначала в файле), оказалось, что следующая кнопка оказалась с правой границей вне карты. ng-if исправляет это, не включая код вообще. (Только что проверили здесь, если есть какие-то скрытые сюрпризы, используя ng-if вместо ng-show)
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 и ng-if получает условие и скрывает от представления элемент директивы в случае, если условие оценивается как false. Однако механики, которые они используют, чтобы скрыть представление, отличаются.
ng-show/ng-hide переключить внешний вид элемента, добавив экран CSS: none style.
а
ng-if, с другой стороны, фактически удаляет элемент из DOM, когда условие является ложным, и только добавляет элемент назад, когда условие становится истинным.
ng-show оставляет элементы живыми в DOM, это означает, что все их часовые выражения и стоимость исполнения все еще существуют, даже если пользователь вообще не видит представление. В случаях, когда у вас есть несколько больших представлений, которые переключаются с помощью ng-show, вы можете заметить, что все немного лаги (например, нажимать на кнопки или вводить внутренние поля ввода).
вы просто замените ng-show на ng-if, что вы можете наблюдать значительные улучшения в реагировании вашего приложения, поскольку эти дополнительные часы больше не происходят.
ngIf выполняет манипуляции с DOM, удаляя или воссоздавая элемент.
В то время как ngShow применяет правила css, чтобы скрыть/показать вещи.
В большинстве случаев (не всегда) я бы обобщил это так: если вам нужно одноразовую проверку, чтобы показать/скрыть вещи, используйте ng-if
, если вам нужно показать/скрыть вещи на основе действий пользователя на экране (например, отметьте флажок, затем покажите текстовое поле, снимите флажок, затем скройте текстовое поле и т.д.), затем используйте ng-show
Одно интересное различие в ng-if и ng-show:
Безопасность
Элементы DOM, присутствующие в блоке ng-if, не будут отображаться в случае его значения как false
где, как и в случае ng-show, пользователь может открыть окно Inspect Element и установить его значение TRUE.
И с воплем отображается все содержимое, предназначенное для скрытия, что является нарушением безопасности.:)