我试图理解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类将从元素中移除,使元素不显示为隐藏状态。

其他回答

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伪选择器来设置样式,这是非常有用的。

@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.

原因是输入字段是存在的,它是必需的,但由于它是隐藏的Chrome不能关注它。这可能会破坏您的代码,因为此错误会停止脚本执行。所以要小心!

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

据我所知,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。