我试图理解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指令根据提供给ngShow属性的表达式来显示或隐藏给定的HTML元素。通过在元素上删除或添加ng-hide CSS类来显示或隐藏元素。.ng-hide CSS类是在AngularJS中预定义的,它将显示样式设置为none(使用!重要标志)。

<!-- 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指令中优先级最高(如果不是最高的话)的指令之一。这意味着:它将在所有其他低优先级的指令之前运行。事实上,它首先运行,意味着有效地,在任何内部指令被处理之前,元素被删除。至少,我是这么认为的。

I observerd and used this in the UI I'm building for my current customer. The entire UI is quite heavily packed, and it had ng-show and ng-hide all over it. Not to go into too much detail, but I built a generic component, which could be managed using JSON config, so I had to do some switching inside the template. There is an ng-repeat present, and inside the ng-repeat, a table is shown, which has a lot of ng-shows, ng-hides and even ng-switches present. They wanted to show at least 50 repeats in the list, which would result in more or less 1500-2000 directives to be resolved. I checked the code, and the Java backend + custom JS on the front would take about 150ms to process the data, and then Angular would chew some 2-3 seconds on it, before displaying. The customer did not complain, but I was appalled :-)

In my search, I stumbled across the ng-if directive. Now, maybe it's best to point out that at the point of conceiving this UI, there was no ng-if available. Because the ng-show and ng-hide had functions in them, which returned booleans, I could easily replace them all with ng-if. By doing so, all inner directives seemed to be no longer evaluated. That meant that I dropped back to about a third of all directives being evaluated, and thus, the UI speeded up to about 500ms - 1 sec loading time. (I have no way to determine exact seconds)

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

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


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

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


@Gajus Kuizinas and @CodeHater are correct. Here i am just giving an example. While we are working with ng-if, if the assigned value is false then the whole html elements will be removed from DOM. and if assigned value is true, then the html elements will be visible on the DOM. And the scope will be different compared to the parent scope. But in case of ng-show, it wil just show and hide the elements based on the assigned value. But it always stays in the DOM. Only the visibility changes as per the assigned value.

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

安全

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

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

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


ng-if if false will remove elements from DOM. This means that all your events, directives attached to those elements will be lost. For example, ng-click to one of child elements, when ng-if evaluates to false, that element will be removed from DOM and again when it is true it is recreated. ng-show/ng-hide does not remove the elements from DOM. It uses CSS styles (.ng-hide) to hide/show elements .This way your events, directives that were attached to children will not be lost. ng-if creates a child scope while ng-show/ng-hide does not.


请注意,现在发生在我身上的一件事: Ng-show通过css隐藏内容,是的,但它导致了奇怪的小故障在div的应该是按钮。

我有一个底部有两个按钮的卡,根据实际状态,一个与第三个交换,示例编辑按钮与新条目。使用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.

原因是输入字段是存在的,它是必需的,但由于它是隐藏的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-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事件,显示变量,从内部/自己的作用域,被改变了,但ng-if正在观察从外部作用域同名的另一个变量,所以解决方案不工作。对于ng-show,我们只有一个show变量,这就是它工作的原因。要修复第一次尝试,我们应该通过$parent.show引用show from parent/outer scope。


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

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

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