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


427

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

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

Ответы:


521

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 на элемент. Класс .ng-hideCSS предопределен в 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, больше не существует.
mrzmyr

3
@CodeHater Я успешно использовал ng-if над ng-show / ng-hide на странице, которая в противном случае имела бы большой дом. Казалось, что страница чувствуется быстрее, но это ни в коем случае не научный анализ.
Эд Спенсер

У меня возникли проблемы с полным пониманием того, как / почему, когда у вас есть объект в модели, data.inputон работает ... но dataодин в модели не работает. @CodeHater
Марк Писак - Trilon.io

7
@mcpDESIGNS ngIfсоздает новую область, поэтому, глядя на приведенный выше пример, ngModelможно создать новую dataмодель, даже если в родительской области существует модель с тем же именем. Но когда вы используете точечную запись, вы заставляете JS искать цепочку прототипов области. Поэтому, если он не найдет значение в текущей области, он попытается найти его в родительской области и так далее. Немногие другие директивы , которые создают различные сферы являются ngInclude, ngRepeat. Надеюсь, теперь все ясно. :)
AlwaysALearner

3
Какой из них лучше для производительности? Я думаю, нг-шоу и нг-скрыть не так ли?
Tom10271

97

Может быть, интересный момент, это разница между приоритетами между ними.

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


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

36

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

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


что вы имеете в виду, используя селектор: first и: last?
Стефан Роллан


16

@EdSpencer правильно. Если у вас много элементов и вы используете ng-if только для создания экземпляров соответствующих элементов, вы экономите ресурсы. @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 не может сосредоточиться на нем. Это может буквально нарушить ваш код, так как эта ошибка останавливает выполнение скрипта. Так что будь осторожен!


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

5

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


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


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

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

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


1

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)


0

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

Принимая во внимание, что ngShow применяет правила CSS для скрытия / показа вещей.

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


-17

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

БЕЗОПАСНОСТЬ

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

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

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


27
Это чрезвычайно слабая форма безопасности. Если контент передается клиенту сервером, вы должны предположить, что пользователь / злоумышленник может получить к нему доступ, независимо от того, присутствует он в DOM или нет. Вся логика авторизации должна выполняться сервером.
tlrobinson

подумайте о html, а не о jsp ... теперь, если вы хотите обеспечить безопасность для html-компонентов ... т.е. если вы хотите скрыть некоторые компоненты от пользователя ... как бы вы этого достигли. И что в случае, если ваша конфигурация разделена на серверную часть для серверной части и клиентскую часть для
внешнего
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.