ng-if和ng-show/ng-hide的区别是什么

我试图理解ng-ifng-show/ng-hide之间的区别,但对我来说它们看起来是一样的。

在选择使用一种或另一种时,我应该记住有什么区别吗?

321791 次浏览

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中创建的作用域使用原型继承继承自其父作用域。

如果在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指令根据提供给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指令从页面中删除内容,而ng-show/ng-hide使用CSS的display属性来隐藏内容。

如果你想使用:first-child:last-child伪选择器来设置样式,这是很有用的。

也许有趣的一点是,两者的优先级不同。

据我所知,ng-if指令是所有Angular指令中优先级最高(如果不是最高的话)的指令之一。这意味着:它将在所有其他低优先级的指令之前运行。事实上,它首先运行,意味着有效地,在任何内心的指令被处理之前,元素被删除。至少,我是这么认为的。

我在为当前客户构建的UI中观察并使用了这一点。整个UI非常密集,到处都是ng-show和ng-hide。我不想讲太多细节,但我构建了一个通用组件,它可以使用JSON配置进行管理,因此我必须在模板内部进行一些切换。有一个ng-repeat present,在ng-repeat中显示了一个表,其中有很多ng-show、ng-hides甚至ng-switches。他们希望在列表中显示至少50个重复,这将导致大约1500-2000个指令被解析。我检查了代码,Java后端+前端的自定义JS需要大约150ms来处理数据,然后Angular会在显示之前花2-3秒的时间处理它。顾客没有抱怨,但我惊呆了:-)

在我的搜索中,我偶然发现了ng-if指令。现在,也许最好指出的是,在构思这个UI时,没有ng-if可用。 因为ng-show和ng-hide包含返回布尔值的函数,所以我可以很容易地将它们全部替换为ng-if。这样一来,所有内部指令似乎都不再计算了。这意味着我将所有正在评估的指令减少到大约三分之一,因此,UI加速到大约500ms - 1秒的加载时间。(我没有办法确定准确的秒数) < / p >

注意:指令没有被评估的事实,是对下面发生的事情的一个有根据的猜测。

所以,在我看来:如果你需要元素出现在页面上(即:检查元素,或其他),但只是被隐藏,请使用ng-show/ng-hide。在所有其他情况下,使用ng-if。

@EdSpencer是正确的。如果您有很多元素,并且使用ng-if只实例化相关的元素,则可以节省资源。 @CodeHater也有点正确,如果你要经常删除和显示一个元素,隐藏它而不是删除它可以提高性能

我发现ng-if的主要用例是,如果内容是非法的,它允许我清晰地验证和消除元素。例如,我可以引用一个空图像名称变量,这将抛出一个错误,但如果我ng-if并检查它是否为空,这一切都很好。如果我执行ng-show,错误仍然会触发。

@Gajus Kuizinas和@CodeHater是正确的。这里我只是举个例子。 当我们使用ng-if时,如果赋值为false,那么整个html元素将从DOM中删除。如果赋值为true,则html元素将在DOM上可见。与父作用域相比,作用域是不同的。但在ng-show的情况下,它只会显示和隐藏基于指定值的元素。但它总是在DOM中。

< a href = " http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p =预览noreferrer“rel = > http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p =预览< / >

希望这个例子能帮助你理解范围。 尝试给ng-show和ng-if赋假值,并在控制台中检查DOM。

.在输入框中输入数值,观察差异
<!DOCTYPE html>

你好砰砰作响!< / h1 >

<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的一个有趣的区别是:

安全

如果ng-if块中的DOM元素值为false,则不会被呈现

在ng-show的情况下,用户可以打开检查元素窗口并将其值设置为TRUE。

随着一声巨响,原本要隐藏的全部内容都显示出来了,这是一个安全漏洞。:)

  1. ng-if if为false将从DOM中删除元素。这意味着附加到这些元素上的所有事件和指令都将丢失。例如,ng-click到其中一个子元素,当ng-if的值为false时,该元素将从DOM中删除,当值为true时重新创建。

  2. ng-show/ng-hide不会从DOM中删除元素。它使用CSS样式(.ng-hide)来隐藏/显示元素,这样你的事件和附加到子元素的指令就不会丢失。

  3. Ng-if创建子作用域,而ng-show/ng-hide不创建子作用域。

注意,现在发生在我身上的一件事: Ng-show通过css隐藏内容,是的,但它导致了奇怪的小故障在div的应该是按钮。< / p > 我有一个底部有两个按钮的卡,根据实际状态,一个与第三个交换,示例编辑按钮与新条目。使用ng-show=false来隐藏左边的按钮(首先出现在文件中),下面的按钮的右边框出现在卡片外面。 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不能关注它。这可能会破坏您的代码,因为此错误会停止脚本执行。所以要小心!

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不同,ng-if指令创建了自己的作用域,这导致了有趣的实际差异:

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

ngIf通过删除或重新创建元素对DOM进行操作。

ngShow应用css规则来隐藏/显示内容。

对于大多数情况(并非总是如此),我将其总结为,如果你需要一次检查来显示/隐藏内容,使用ng-if,如果你需要根据用户在屏幕上的操作显示/隐藏内容(比如选中复选框然后显示文本框,未选中然后隐藏文本框等),那么使用ng-show