我试图了解ng-if
和ng-show
/ng-hide
之间的区别,但它们对我来说看起来是一样的。
我应该记住选择使用其中一种有什么区别吗?
ngIf
ngIf
指令基于表达式删除或重新创建 DOM 树的一部分。如果分配给 ngIf
的表达式的计算结果为 false 值,则会从 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
中创建的作用域使用原型继承从其父作用域继承。
如果在ngIf
中使用ngModel
绑定到父作用域中定义的 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 元素。通过删除或向元素添加 ng-hide
CSS 类来显示或隐藏元素。.ng-hide
CSS 类在 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 的事实意味着在处理任何内部指令之前有效地删除了元素。或者至少:这就是我的看法。
我在为当前客户构建的 UI 中观察并使用它。整个UI非常繁重,并且到处都是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指令。现在,也许最好指出,在构思此UI时,没有ng-if可用。因为 ng-show 和 ng-hide 中有返回布尔值的函数,所以我可以轻松地将它们全部替换为 ng-if。通过这样做,所有内部指令似乎都不再被评估。这意味着我回落到正在评估的所有指令的三分之一左右,因此,UI 速度加快到大约 500 毫秒 - 1 秒加载时间。(我无法确定确切的秒数(
请注意:指令未被评估的事实是对下面发生的事情的有根据的猜测。
所以,在我看来:如果你需要元素出现在页面上(即:用于检查元素或其他什么(,但只是隐藏,使用 ng-show/ng-hide。在所有其他情况下,请使用 ng-if。
ng-if
指令从页面中删除内容,ng-show/ng-hide
使用 CSS display
属性隐藏内容。
使用:first-child
和:last-child
伪选择器来设置样式,这很有用。
@EdSpencer是正确的。如果你有很多元素,并且你使用 ng-if 只实例化相关的元素,你就在节省资源。@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无法专注于它。这可能会破坏您的代码,因为此错误会停止脚本执行。所以要小心!
@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 提供 false 值,并在控制台中检查 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
变量,这就是它工作的原因。要修复第一次尝试,我们应该通过 $parent.show
引用父/外部范围中的show
。
-
ng-if if if 将从 DOM 中删除元素。这意味着附加到这些元素的所有事件和指令都将丢失。例如,ng-单击到其中一个子元素,当 ng-if 的计算结果为 false 时,该元素将从 DOM 中删除,当它为 true 时,它将再次被重新创建。
-
ng-show/ng-hide 不会从 DOM 中删除元素。它使用CSS样式(.ng-hide(来隐藏/显示元素。这样,您的事件,附加到儿童的指令将不会丢失。
-
ng-if 创建一个子作用域,而 ng-show/ng-hide 不会。
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确实通过CSS隐藏了内容,是的,但它导致了div应该是按钮的奇怪故障。
我有一张底部有两个按钮的卡片,根据实际状态,一张与第三个交换,示例编辑按钮与新条目交换。使用 ng-show=false 隐藏左边框(首先出现在文件中(,碰巧以下按钮最终出现在卡片外的右边框。ng-if 通过根本不包含代码来解决此问题。(刚刚在这里检查是否有一些隐藏的惊喜使用 ng-if 而不是 ng-show(
ngIf 通过删除或重新创建元素对 DOM 进行操作。
而ngShow应用css规则来隐藏/显示事物。
对于大多数情况(并非总是如此(,我会将其总结为,如果您需要一次性检查来显示/隐藏内容,请使用ng-if
,如果您需要根据屏幕上的用户操作显示/隐藏内容(例如选中复选框然后显示文本框,取消选中然后隐藏文本框等(,然后使用ng-show
ng-if和ng-show的一个有趣的区别是:
安全
ng-if 块中存在的 DOM 元素在其值为 false 的情况下不会呈现
与ng-show的情况一样,用户可以打开"检查元素窗口"并将其值设置为TRUE。
随着一声呜呜声,本应隐藏的全部内容都会被显示出来,这是一个安全漏洞。 :)