в чем разница между ng-if и ng-show / ng-hide

406

Я пытаюсь понять разницу между ng-if и ng-show/ng-hide, но они выглядят одинаково для меня.

Есть ли разница, которую я должен иметь в виду, предпочитая использовать один или другой?

Теги:
angularjs-ng-if
angularjs-ng-show

13 ответов

528
Лучший ответ

ngIf

Директива 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

Директива 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 удаляется из элемента, заставляя элемент не казаться скрытым.

  • 31
    Подсказка: удалив сам HTML-элемент с помощью ng-if модель, добавленная с помощью ng-model , больше не существует.
  • 3
    @CodeHater Я успешно использовал ng-if над ng-show / ng-hide на странице, которая в противном случае имела бы большой дом. Казалось, что страница чувствуется быстрее, но это ни в коем случае не научный анализ.
Показать ещё 9 комментариев
92

Возможно, интересный момент - разница между приоритетами между ними.

Насколько я могу судить, директива 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.

  • 1
    Да, я думаю, что это цель ng-if: сократить время обработки. Эта директива существует наверняка не только из-за некоторых псевдоселекторов CSS. Хороший пост! +1
37

Директива ng-if удаляет содержимое со страницы, а ng-show/ng-hide использует свойство CSS display, чтобы скрыть содержимое.

Это полезно, если вы хотите использовать псевдо-селектора :first-child и :last-child для стиля.

16

@EdSpencer верен. Если у вас много элементов, и вы используете ng - если вы только создаете экземпляр соответствующих, вы сохраняете ресурсы. @CodeHater также несколько правилен, если вы собираетесь удалить и показать элемент очень часто, скрывая его, а не удаляя его, это может повысить производительность.

Основной случай использования, который я нахожу для ng-if, заключается в том, что он позволяет мне чисто проверять и исключать элемент, если содержимое является незаконным. Например, я мог бы ссылаться на переменную имени нулевого изображения, и это вызовет ошибку, но если я ng-if и проверьте, является ли оно нулевым, все это хорошо. Если я сделал ng-show, ошибка все равно будет срабатывать.

7

Одна из важных замечаний о 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. Будьте осторожны!

  • 0
    Это реальный факт, если вы используете элементы управления формой для проверки, то вы сильно пострадаете, если будете использовать ng-show / ng-hide. И если у вас есть несколько скрытых разделов / шоу на основе выражения. Поэтому, если вы используете ng-show / hide, элементы все еще будут там, и проверка не будет выполнена, несмотря на то, что они не отображаются на экране. так что если вас спасти :)
5

@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>

        

  

Привет, Plunker!

<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}}

2

Факт, что директива 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, из области innner/own, но ng-if просматривает другую переменную из external scope с тем же именем, поэтому решение не работает. В случае ng-show мы имеем единственную переменную show, поэтому она работает. Чтобы исправить первую попытку, мы должны ссылаться на show из родительской/внешней области с помощью $parent.show.

1
  • ng - если false приведет к удалению элементов из DOM. Это означает, что все ваши события, директивы, привязанные к этим элементам, будут потеряны. Например, ng-click для одного из дочерних элементов, когда ng-if оценивает значение false, этот элемент будет удален из DOM и снова, когда он верен, он воссоздается.

  • ng-show/ng-hide не удаляет элементы из DOM. Он использует стили CSS (.ng-hide), чтобы скрыть/показать элементы. Таким образом ваши события, директивы, прикрепленные к детям, не будут потеряны.

  • ng-if создает дочернюю область, пока ng-show/ng-hide не делает.

0

ngIf выполняет манипуляции с DOM, удаляя или воссоздавая элемент.

В то время как ngShow применяет правила css, чтобы скрыть/показать вещи.

В большинстве случаев (не всегда) я бы обобщил это так: если вам нужно одноразовую проверку, чтобы показать/скрыть вещи, используйте ng-if, если вам нужно показать/скрыть вещи на основе действий пользователя на экране (например, отметьте флажок, затем покажите текстовое поле, снимите флажок, затем скройте текстовое поле и т.д.), затем используйте ng-show

0

ng-show и ng-if получает условие и скрывает от представления элемент директивы в случае, если условие оценивается как false. Однако механики, которые они используют, чтобы скрыть представление, отличаются.

ng-show/ng-hide переключить внешний вид элемента, добавив экран CSS: none style.

а

ng-if, с другой стороны, фактически удаляет элемент из DOM, когда условие является ложным, и только добавляет элемент назад, когда условие становится истинным.

ng-show оставляет элементы живыми в DOM, это означает, что все их часовые выражения и стоимость исполнения все еще существуют, даже если пользователь вообще не видит представление. В случаях, когда у вас есть несколько больших представлений, которые переключаются с помощью ng-show, вы можете заметить, что все немного лаги (например, нажимать на кнопки или вводить внутренние поля ввода).

вы просто замените ng-show на ng-if, что вы можете наблюдать значительные улучшения в реагировании вашего приложения, поскольку эти дополнительные часы больше не происходят.

0

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. 
0

Чтобы заметить, что случилось со мной сейчас: ng-show действительно скрывает содержимое через css, да, но это привело к странным сбоям в div, которые должны быть кнопками.

У меня была карта с двумя кнопками внизу и в зависимости от фактического состояния, которое обменивается с третьей кнопкой редактирования примера с новой записью. Используя ng-show = false, чтобы скрыть левый (присутствующий сначала в файле), оказалось, что следующая кнопка оказалась с правой границей вне карты. ng-if исправляет это, не включая код вообще. (Только что проверили здесь, если есть какие-то скрытые сюрпризы, используя ng-if вместо ng-show)

-16

Одно интересное различие в ng-if и ng-show:

Безопасность

Элементы DOM, присутствующие в блоке ng-if, не будут отображаться в случае его значения как false

где, как и в случае ng-show, пользователь может открыть окно Inspect Element и установить его значение TRUE.

И с воплем отображается все содержимое, предназначенное для скрытия, что является нарушением безопасности.:)

  • 26
    Это чрезвычайно слабая форма безопасности. Если контент передается клиенту сервером, вы должны предположить, что пользователь / злоумышленник может получить к нему доступ, независимо от того, присутствует он в DOM или нет. Вся логика авторизации должна выполняться сервером.
  • 0
    подумайте о html, а не о jsp ... теперь, если вы хотите обеспечить безопасность для html-компонентов ... т.е. если вы хотите скрыть некоторые компоненты от пользователя ... как бы вы этого достигли. А что в случае, если ваша конфигурация разделена на серверную часть для серверной части и клиентскую часть для интерфейсной части?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню