Я намагаюся зрозуміти різницю між 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 і встановлює жодний стиль відображення (використовуючи !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
клас class
атрибуту CSS додається до атрибуту елемента, що призводить до його приховання. Коли true
, то ng-hide
клас CSS видаляються з елемента викликає елемент не з'являтися приховано.
data.input
він працює ... але в data
самоті в моделі не працює. @CodeHater
ngIf
створює нову область застосування, тому, дивлячись на приклад вище вкладеного ngModel
, створила б нову data
модель, навіть незважаючи на те, що модель з тим самим іменем існує в батьківській області. Але коли ви використовуєте крапкові позначення, ви змушуєте JS шукати прототип ланцюга області. Тож якщо воно не знайде значення у поточній області, воно спробує шукати його у батьківській області тощо. Деякі інші директиви , які створюють різні сфери є ngInclude
, ngRepeat
. Сподіваюся, це зрозуміло зараз. :)
Можливо, цікавим моментом є різниця між пріоритетами між обома.
Наскільки я можу сказати, директива ng-if має один із найвищих (якщо не найвищий) пріоритет усіх кутових директив. Що означає: вона запуститься ПЕРШИМО перед усіма іншими директивами з нижчим пріоритетом. Те, що він працює ПЕРШИЙ, означає, що ефективно, елемент видаляється перед тим, як будь-які внутрішні директиви будуть оброблені. Або принаймні: саме з цього я роблю.
Я спостерігав і використовував це в інтерфейсі, який будую для свого поточного замовника. Весь інтерфейс досить сильно упакований, і він мав ng-show та ng-приховування по всьому. Щоб не вдаватися до занадто багато деталей, але я створив загальний компонент, яким можна керувати за допомогою конфігурації JSON, тому мені довелося зробити деякий перемикання всередині шаблону. Існує присутність ng-повторів, а всередині ng-повторення показана таблиця, в якій присутня безліч ng-шоу, ng-шкур і навіть ng-перемикачів. Вони хотіли показати принаймні 50 повторів у списку, що призведе до того, щоб було вирішено більш-менш 1500-2000 директив. Я перевірив код, і Java Bakend + користувальницький JS на передній панелі займе близько 150 мс для обробки даних, і тоді Angular пережовує їх за 2-3 секунди, перш ніж показувати. Клієнт не поскаржився, але я був вражений :-)
У своєму пошуку я натрапив на директиву ng-if. Тепер, можливо, найкраще зазначити, що на момент створення цього інтерфейсу не було ng - якщо воно було доступне. Оскільки ng-show і ng-hid мали функції в них, які повертали булеві, я міг легко замінити їх усі ng-if. Тим самим всі внутрішні директиви, здавалося, більше не оцінювалися. Це означало, що я повернувся до приблизно третини всіх директив, що оцінюються, і, таким чином, інтерфейс прискорився приблизно до 500 мс - час завантаження на 1 сек. (Я не можу визначити точні секунди)
Зверніть увагу: той факт, що директиви не оцінюються, є освіченою здогадкою про те, що відбувається внизу.
Отже, на мою думку: якщо вам потрібен елемент, який повинен бути присутнім на сторінці (тобто для перевірки елемента, або будь-якого іншого), а просто бути прихованим, використовуйте ng-show / ng-hid. У всіх інших випадках використовуйте 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-шоу, помилка все-таки виникла б.
Одним важливим, що слід зазначити про 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. а якщо присвоєне значення вірно, то елементи 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 if false буде видаляти елементи з DOM. Це означає, що всі ваші події, директиви, приєднані до цих елементів, будуть втрачені. Наприклад, клацніть ng на одному з дочірніх елементів, коли ng-if оцінюється як false, цей елемент буде видалено з DOM і знову, коли це правда, він буде відтворений.
ng-show / ng-hid не видаляє елементи з DOM. Він використовує стилі CSS (.ng-hid), щоб приховати / показати елементи. Таким чином ваші події, директиви, прикріплені до дітей, не будуть втрачені.
ng-if створює дочірню область, тоді як ng-show / ng-hid не робить.
ng-show і ng-hid працюють протилежно. Але різниця між ng-hid або ng-show з ng-якщо є, якщо ми використовуємо ng-if, тоді елемент буде створений у dom, але з ng-hid / 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, так, але це призвело до дивних збоїв у діві, які повинні бути кнопками.
У мене була карта з двома кнопками внизу, і залежно від фактичного стану одна обмінюється на третю, наприклад кнопку редагування з новим записом. Використовуючи ng-show = false, щоб приховати ліву (присутня спочатку у файлі), сталося, що наступна кнопка виявилася правою межею поза карткою. ng-if виправляє це, не включаючи код взагалі. (Просто перевірте тут, чи є якісь приховані сюрпризи, які використовують ng-if замість ng-show)
ngIf робить маніпуляцію на DOM, видаляючи або відтворюючи елемент.
Тоді як ngShow застосовує правила css для приховування / показу речей.
У більшості випадків (не завжди) я б підсумував це так, якщо вам потрібно одноразово перевірити, щоб показати / приховати речі, використовувати ng-if
, якщо вам потрібно показувати / приховувати речі на основі дій користувача на екрані (наприклад, зареєстровано Поставте прапорець, потім покажіть текстове поле, зніміть прапорець, потім прихойте текстове поле тощо), а потім використовуйтеng-show
Одна цікава різниця в ng-if і ng-show:
БЕЗПЕКА
Елементи DOM, присутні в блоці ng-if, не будуть надані у випадку його значення як помилкового
де, як і у випадку з ng-show, користувач може відкрити вікно елемента перевірки елементів і встановити його значення на TRUE.
І з вершиною, весь вміст, який мав бути прихований, відображається, що є порушенням безпеки. :)
ng-if
моделлю, доданий користувачемng-model
, більше не існує.