Когда отдать предпочтение нг-если против нг-шоу / нг-скрыть?

516

Я понимаю это ng-showи ng-hideвлияю на набор классов для элемента, и это ng-ifконтролирует, отображается ли элемент как часть DOM.

Существуют ли рекомендации по выбору ng-ifболее ng-show/ ng-hideили наоборот?

Патрис Чалин
источник
5
возможная копия того, в чем разница между ng-if и ng-show / ng-hide
Gajus
1
Не относится к языку дартс .
naXa

Ответы:

703

Зависит от вашего варианта использования, но суммируя разницу:

  1. ng-ifудалит элементы из DOM. Это означает, что все ваши обработчики или что-либо еще, прикрепленное к этим элементам, будут потеряны. Например, если вы привязали обработчик щелчка к одному из дочерних элементов, когда ng-ifзначение равно false, этот элемент будет удален из DOM, и ваш обработчик щелчков больше не будет работать, даже после того, как ng-ifпозднее значение станет равным true и отобразит элемент. Вам нужно будет снова прикрепить обработчик.
  2. ng-show/ng-hideне удаляет элементы из DOM. Он использует стили CSS для скрытия / отображения элементов (примечание: вам может понадобиться добавить свои собственные классы). Таким образом, ваши обработчики, которые были привязаны к детям, не будут потеряны.
  3. ng-ifсоздает дочернюю область, пока ng-show/ng-hideне

Элементы, которых нет в DOM, оказывают меньшее влияние на производительность, и ваше веб-приложение может работать быстрее по ng-ifсравнению с ng-show/ng-hide. По моему опыту, разница незначительна. Анимации возможны при использовании обоих ng-show/ng-hideи ng-ifс примерами для обоих в документации Angular.

В конечном итоге, вам нужно ответить на вопрос: можете ли вы удалить элемент из DOM или нет?

markovuksanovic
источник
19
Вы можете использовать CSS3 анимацию с ng-if. Проверьте параграф Анимации и пример в документах . Также с ng-hide/ng-showселекторами CSS, как :first-childили :nth-childне будет работать должным образом, так как скрытые элементы также будут учитываться.
Лукаш Войцеховский
4
Сервис анимации в angular.dart является относительно новым. На момент написания этого он был недоступен.
markovuksanovic
44
Во-первых, это не проблема, если вы используете директивы (например, ng-click) для привязки обработчиков, как и должно быть.
Кевин С.
9
Кроме того, ng-ifсоздает новую область, пока ng-showнет.
мартин
8
Также следует отметить, что добавление и удаление элементов из DOM может повлечь за собой высокую производительность, если это делается часто.
Кевин С.
130

Смотрите здесь для CodePen, который демонстрирует разницу в том, как работает ng-if / ng-show, с точки зрения DOM.

@markovuksanovic хорошо ответил на вопрос. Но я бы пришел к этому с другой точки зрения: я всегда использовал ng-ifи извлекал эти элементы из DOM, если только:

  1. по какой-то причине вам нужны привязки данных и $watch-es на ваших элементах, чтобы они оставались активными, пока они невидимы. Формы могут быть хорошим примером для этого, если вы хотите иметь возможность проверять достоверность входных данных, которые в данный момент не видны, чтобы определить, является ли вся форма действительной.
  2. Вы используете действительно сложную логику состояния с обработчиками условных событий, как упомянуто выше. Тем не менее , если вы обнаружите, что вручную подключаете и отключаете обработчики, так что вы теряете важное состояние при использовании ng-if, спросите себя, будет ли это состояние лучше представлено в модели данных, а обработчики применяются условно с помощью директив всякий раз, когда элемент отображается Другими словами, наличие / отсутствие обработчиков является формой данных о состоянии. Получите эти данные из DOM и в модель. Наличие / отсутствие обработчиков должно определяться данными, и, следовательно, их легко воссоздать.

Angular написан действительно хорошо. Это быстро, учитывая, что он делает. Но то, что он делает, - это целая куча магии, которая делает сложные вещи (такие как двухстороннее связывание данных) тривиально простыми. Чтобы все это выглядело легко, нужно немного снизить производительность. Вы можете быть потрясены, когда поймете, сколько сотен или тысяч раз оценивается функция сеттера в течение $digestцикла на куске DOM, на который никто даже не смотрит. И тогда вы понимаете, что десятки или сотни невидимых элементов делают одно и то же ...

Рабочие столы действительно могут быть достаточно мощными, чтобы сделать большинство проблем со скоростью выполнения JS спорными. Но если вы разрабатываете для мобильных устройств, использование ng-if, если это возможно, должно быть легким делом. Скорость JS по-прежнему важна для мобильных процессоров. Использование ng-if - это очень простой способ получить потенциально значимую оптимизацию при очень и очень низких затратах.

XML
источник
6
Очень хорошее дополнение к ответу выше. Дано с хорошим контекстом, который также помогает в принятии решений. Спасибо.
Шон
1
ng-showможет быть полезным, когда у вас есть, скажем, вкладки, каждая из которых содержит много контента, который занимает время для визуализации. После первого рендеринга перемещение между вкладками будет мгновенным, тогда какng-if потребуется повторный рендеринг, привязка событий и т. Д. Как вы можете сказать, недостатком является создание часов, выполняющихся в фоновом режиме. Angular отчаянно нуждаетсяng-ifshowwatch
шикарный
53

Из моего опыта:

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

2) ng-if создаст / уничтожит область видимости, когда оценивается как true / false. Если к ng-if подключен контроллер, этот код контроллера будет выполняться каждый раз, когда ng-if оценивается как true. Если вы используете ng-show, код контроллера выполняется только один раз. Поэтому, если у вас есть кнопка, которая переключается между несколькими представлениями, использование ng-if и ng-show очень сильно изменит способ написания кода контроллера.

Yi Z
источник
5
Это огромная правда! нг-если не обязательно сделать ваш интерфейс быстрее. Это зависит от ваших потребностей. На самом деле это может быть наоборот, если вы используете в неправильной ситуации.
Тьяго С. С Вентура
1
Но, по моему мнению, ng-if не рендерится на DOM, поэтому он быстрый по сравнению с ng-show / hide. я не прав, пожалуйста, дайте мне исправить в этой точке.
Пардип Джейн
1
ng-if будет быстрее, если он оценивается как false, поскольку, как вы говорите, ничего не нужно вставлять в DOM. Но, если это так, у вас есть издержки на вставку - возможно, довольно сложного - элемента в DOM.
Mawg говорит восстановить Монику
«2) ng-if создаст / уничтожит область видимости, когда она получит значение true / false. Если к ng-if подключен контроллер, этот код контроллера будет выполняться каждый раз»
The Red Pea
35

Ответ не прост:

Это зависит от целевых машин (мобильный или настольный компьютер), от природы ваших данных, браузера, операционной системы, аппаратного обеспечения, на котором он работает ... вам нужно будет тестировать, если вы действительно хотите знать.

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

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

  • ng-if : если элементы, скорее всего, не будут отображаться (разреженно), просто создайте их и уничтожьте их в режиме реального времени, особенно если их содержимое требует больших затрат (вычисления / сортировка / фильтрация, изображения, созданные изображения). Это идеально для редких элементов или элементов «по требованию», оно экономит память с точки зрения незаполнения DOM, но может стоить больших вычислений (создание / уничтожение элементов) и пропускной способности (получение удаленного контента). Это также зависит от того, сколько вы вычисляете в представлении (фильтрация / сортировка) по сравнению с тем, что у вас уже есть в модели (предварительно отсортированные / предварительно отфильтрованные данные).

Кристоф Русси
источник
2
Другие ответы на технические факты. Это для мудрости. Вы четко создали нетривиальные приложения Angular, сэр! +1
лучший
Эта проблема выходит за рамки углов, это фундаментальная проблема в информатике, есть точка, с которой один метод более эффективен, чем другой. Обычно это можно найти с помощью некоторого сравнительного анализа. Таким образом, вы можете даже переключаться между одним методом и другим в зависимости от количества предметов ... Подобная тема: math.stackexchange.com/questions/1632739/…
Кристоф Русси,
12

Одно важное замечание:

ngIf (в отличие от ngShow) обычно создает дочерние области, которые могут давать неожиданные результаты.

У меня была проблема, связанная с этим, и я потратил НАМНОГО времени, чтобы выяснить, что происходит.

(Моя директива записывала значения модели в неверную область.)

Поэтому, чтобы сохранить свои волосы, просто используйте ngShow, если вы не слишком медленно бегаете.

Разница в производительности едва заметна в любом случае, и я пока не уверен, кому это выгодно, без теста ...

user2173353
источник
8
Использование $parent.scopevarпривязок данных в ngIf исправит проблемы, связанные с дочерними областями, при использовании ngIf
meconroy
2
Это не совсем верно (то есть оригинальный комментарий @ user2173353). Если вы будете придерживаться хорошей практики, у вас не будет проблем. Это довольно простое правило: «если нет точки, вы делаете это неправильно». Смотрите здесь для демонстрации того, как это работает: bit.ly/1SPv4wL . Еще одна замечательная ссылка (см. Ошибку № 2): bit.ly/1QfFeWd > (Моя директива записывала значения своей модели в неправильную область.) Это результат того, что мы не придерживались вышеуказанной практики.
piotr.d
1
@ piotr.d Вы правы, но это не то, на чем новичку, возможно, нужно сосредоточиться, и есть еще одна лучшая практика, которая говорит, что лучше оставить улучшения производительности для конца (особенно улучшения производительности, которые не могут быть улучшениями в реальности. ). Я видел, как люди ngIfповсюду полагали, что это улучшит производительность. Это просто не соответствует действительности, и нельзя сказать, что лучше, ngIfили ngShowбез теста или глубокого анализа в конкретном случае. Итак, я все еще рекомендую забыть о том ngIf, что пока кто-то не видит плохую производительность или не знает, что он делает
user2173353
2
Хорошая точка зрения. Но использование контроллера как делает это не проблема. Смотрите, например, Джон Папа о контроллерах As и VM .
jsruok
4

ng-if на ng-include и на ng-controller будет иметь большое влияние на ng-include, он не будет загружать требуемую часть и не обрабатывать, если для ng-controller не установлено значение true, он не будет загружать контроллер, если флаг не установлен истина, но проблема в том, что когда флаг становится ложным в ng, если он удаляется из DOM, когда флаг возвращается в истинное значение, он перезагружает DOM, в этом случае ng-show лучше, на один раз лучше показывает ng-if

Саад Ахмед
источник
4

Если вы используете ng-show or ng-hide контент (например, миниатюры с сервера), будут загружаться независимо от значения выражения, но будут отображаться на основе значения выражения.

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

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

appdroid
источник
Это особенно полезно, так как большинство браузеров будут загружать изображения, даже если CSS скрывает свои DOM-контейнеры. Обычно они просто ищут srcатрибут imgтега, когда он присутствует, он загружается!
Кристоф Русси