ng-if和ng-show / ng-hide有什么区别

时间:2013-10-04 09:26:15

标签: angularjs angularjs-ng-show angularjs-ng-if

我试图了解ng-ifng-show / ng-hide之间的区别,但它们看起来与我相同。

我是否应该记住选择使用其中一种?

12 个答案:

答案 0 :(得分:508)

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内创建的范围继承自其父范围,使用原型继承。

如果在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指令根据提供给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>

                 

    

Hello Plunker!

<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)

  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则不创建。

答案 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,显示要隐藏的所有内容,这是一个安全漏洞。 :)