提问



我试图理解ng-ifng-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(使用!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


也许一个有趣的观点是两者之间的优先级之间的差异。


据我所知,ng-if指令具​​有所有Angular指令中最高(如果不是最高)的优先级之一。这意味着:它将在所有其他更低优先级指令之前运行FIRST。它运行FIRST的事实意味着有效地,在处理任何内部指令之前删除该元素。或者至少:这就是我所做的。


我观察并在用户界面中使用它,我正在为我现在的客户构建。整个用户界面非常庞大,并且整个界面都有ng-show和ng-hide。不要过多细节,但我建立了一个通用组件,可以使用JSON配置进行管理,所以我不得不在模板内进行一些切换。有一个ng-repeat存在,并且在ng-repeat中,显示了一个表,其中有很多ng-显示,ng-hides甚至ng-switch都存在。他们想在列表中显示至少50个重复,这将导致或多或少的1500-2000指令得到解决。我检查了代码,以及Java后端+自定义前面的JS需要大约150ms来处理数据,然后Angular会在显示之前咀嚼2-3秒钟。客户没有抱怨,但我感到震惊:-)


在我的搜索中,我偶然发现了ng-if指令。现在,也许最好指出,在构思这个UI的时候,没有任何可用的东西。
因为ng-show和ng-hide具有返回布尔值的功能,所以我可以用ng-if轻松替换它们。通过这样做,似乎不再评估所有内部指令。这意味着我退回到所评估的所有指令的大约三分之一,因此,UI加速到大约500毫秒 - 加载时间为1秒。 (我无法确定确切的秒数)


请注意:未对指令进行评估的事实是对下面发生的事情的有根据的猜测。


因此,在我看来:如果您需要在页面上显示元素(即:用于检查元素或其他),只需隐藏,请使用ng-show/ng-hide。在所有其他情况下,使用ng-if。

其它参考2


ng-if指令从页面中删除内容,ng-show/ng-hide使用CSS display属性隐藏内容。


如果您想使用:first-child:last-child伪选择器来设置样式,这非常有用。

其它参考3


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


我发现ng-if的主要用例是,如果内容是非法的,它允许我干净地验证和删除元素。例如,我可以引用一个空图像名称变量,这将引发一个错误,但如果我知道并检查它是否为空,那一切都很好。如果我做了ng-show,那么错误仍然会触发。

其它参考4


关于ng-if和ng-show的一个重要注意事项是,当使用表单控件时,最好使用ng-if因为它完全从dom中删除了元素。


这种差异非常重要,因为如果您使用required="true"创建输入字段,然后设置ng-show="false"来隐藏它,Chrome会在用户尝试提交表单时抛出以下错误:


An invalid form control with name='' is not focusable.


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

其它参考5


@ Gajus Kuizinas和@CodeHater都是对的。我在这里举个例子。
当我们使用ng-if时,如果指定的值为false,那么整个html元素将从DOM中删除。如果赋值为true,那么html元素将在DOM上可见。与父范围相比,范围将有所不同。但是在ng-show的情况下,它只会根据指定的值显示和隐藏元素。但它总是留在DOM中。只有可见性根据指定的值更改。


http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview[44]


希望这个例子能帮助你理解范围。
尝试给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



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


其它参考7


事实上,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>



要注意,现在发生在我身上的事情:
ng-show确实通过css隐藏了内容,是的,但它导致div中的奇怪故障应该是按钮。


我有一张卡片,底部有两个按钮,根据实际状态,一个用第三个示例编辑按钮与新条目交换。使用ng-show=false来隐藏左边的一个(文件中的第一个),发生了以下按钮最终在卡外面的右边框。
ng-if通过不包括代码来修复它。
(如果有一些隐藏的惊喜使用ng-if而不是ng-show,请检查这里)

其它参考8


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. 

其它参考9


ng-if和ng-show的一个有趣的区别是:


安全


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


在ng-show的情况下,用户可以打开Inspect Element Window并将其值设置为TRUE。


并且有了一个呐喊,显示了要隐藏的整个内容,这是一个安全漏洞。 :)