我试图了解ng-if
和ng-show
/ ng-hide
之间的区别,但它们看起来与我相同。
我是否应该记住选择使用其中一种?
答案 0 :(得分:508)
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
内创建的范围继承自其父范围,使用原型继承。
如果在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元素。通过将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类,导致元素不显示为隐藏。
答案 1 :(得分:93)
可能有趣的一点是,两者之间的优先级之间存在差异。
据我所知,ng-if指令具有所有Angular指令中最高(如果不是最高)的优先级之一。这意味着:它将在所有其他更低优先级指令之前运行FIRST。它运行FIRST的事实意味着有效地,在处理任何内部指令之前删除该元素。或者至少:这就是我所做的。
我观察并在我正在为当前客户构建的UI中使用它。整个用户界面非常庞大,并且整个界面都有ng-show和ng-hide。不要过多细节,但我构建了一个通用组件,可以使用JSON配置进行管理,所以我不得不在模板中进行一些切换。存在ng-repeat,并且在ng-repeat内部显示了一个表格,其中包含大量的ng-shows,ng-hides甚至ng-switch。他们希望在列表中显示至少50个重复,这将导致或多或少的1500-2000指令得到解决。我检查了代码,前面的Java后端+自定义JS需要大约150ms来处理数据,然后Angular会在显示之前咀嚼2-3秒。客户没有抱怨,但我感到震惊:-)
在我的搜索中,我偶然发现了ng-if指令。现在,也许最好指出,在构思这个用户界面时,没有ng-如果可用的话。 因为ng-show和ng-hide具有返回布尔值的功能,所以我可以用ng-if轻松替换它们。通过这样做,似乎不再评估所有内部指令。这意味着我退回到所评估的所有指令的大约三分之一,因此,UI加速到大约500毫秒 - 加载时间为1秒。 (我无法确定确切的秒数)
请注意:未对指令进行评估的事实是对下面发生的事情的有根据的猜测。
因此,在我看来:如果您需要在页面上显示元素(即:用于检查元素或其他),只需隐藏,请使用ng-show / ng-hide。在所有其他情况下,使用ng-if。
答案 2 :(得分:36)
ng-if
指令从页面中删除内容,ng-show/ng-hide
使用CSS display
属性隐藏内容。
如果您想使用:first-child
和:last-child
伪选择器进行样式处理,这非常有用。
答案 3 :(得分:16)
@EdSpencer是正确的。如果你有很多元素并且你使用ng-if只实例化相关元素,那么你就节省了资源。 @CodeHater也有点正确,如果您要经常删除并显示元素,隐藏它而不是删除它可以提高性能。
我发现ng-if的主要用例是,如果内容是非法的,它允许我干净地验证和删除元素。例如,我可以引用一个空图像名称变量,这会抛出一个错误,但是如果我知道并检查它是否为空,那么它就是好的。如果我做了ng-show,那么错误仍然会触发。
答案 4 :(得分:7)
关于ng-if和ng-show的一个重要注意事项是,当使用表单控件时,最好使用clear
,因为它会从dom中完全删除元素。
这种差异非常重要,因为如果您创建一个包含ng-if
的输入字段,然后设置required="true"
来隐藏它,Chrome会在用户尝试提交表单时抛出以下错误:
ng-show="false"
输入字段的原因是An invalid form control with name='' is not focusable.
,但由于隐藏了Chrome,因此无法关注它。这可能会破坏您的代码,因为此错误会停止脚本执行。所以要小心!
答案 5 :(得分: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}}
答案 6 :(得分: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
正在关注来自<的另一个变量strong>外部范围具有相同名称,因此解决方案不起作用。在ng-show
的情况下,我们只有一个show
变量,这就是它工作的原因。要修复首次尝试,我们应通过show
从父/外范围引用$parent.show
。
答案 7 :(得分:1)
ng-if if false将从DOM中删除元素。这意味着您的所有事件,附加到这些元素的指令都将丢失。例如,ng-click到其中一个子元素,当ng-if计算结果为false时,该元素将从DOM中删除,如果为true,则重新创建它。
ng-show / ng-hide不会从DOM中删除元素。它使用CSS样式(.ng-hide)隐藏/显示元素。这样,您的事件,附加到子项的指令不会丢失。
ng-if创建子范围,而ng-show / ng-hide则不创建。
答案 8 :(得分:0)
要注意,现在发生在我身上的事情: ng-show确实通过css隐藏了内容,是的,但它导致了div应该是按钮的奇怪故障。
我有一张底部有两个按钮的卡片,根据实际状态,一个用第三个示例编辑按钮与新条目交换。使用ng-show = false来隐藏左边的一个(在文件中首先出现),发生了以下按钮最终在卡外面的右边框。 ng-if通过不包括代码来修复它。 (如果有一些隐藏的意外,请使用ng-if代替ng-show进行检查)
答案 9 :(得分: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.
答案 10 :(得分:0)
ngIf 通过删除或重新创建元素来对DOM进行操作。
ngShow 应用CSS规则隐藏/显示内容。
对于大多数情况(并非总是如此),我将其总结为:如果您需要一次检查以显示/隐藏事物,请使用ng-if
,如果需要根据屏幕上的用户操作显示/隐藏事物(例如选中一个复选框然后显示文本框,未选中然后隐藏文本框等。),然后使用ng-show
答案 11 :(得分:-16)
ng-if和ng-show的一个有趣的区别是:
安全强>
如果其值为false
,则不会呈现ng-if块中存在的DOM元素在ng-show的情况下,用户可以打开Inspect Element Window并将其值设置为TRUE。
使用whoop,显示要隐藏的所有内容,这是一个安全漏洞。 :)