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

我应该牢记选择使用其中一个还是另一个吗?

#1 楼

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

如果在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类,从而使该元素不会显示为隐藏。

评论


提示:如果用ng-model添加的模型不再存在,则通过ng删除HTML元素本身。

– mrzmyr
2014年1月6日17:33



@CodeHater我已经成功地在页面上使用ng-if而不是ng-show / ng-hide,否则该页面会有很大的dom。它似乎使页面感觉更快,但绝非科学分析。

– Ed Spencer
2014年3月24日10:33

我无法完全理解的部分是如何/为什么在模型data.input中有对象时它可以工作...但是模型中的单独数据不起作用。 @CodeHater

– Mark Pieszak-Trilon.io
14年6月13日在22:42

@mcpDESIGNS ngIf创建一个新的作用域,因此,即使父作用域中存在一个具有相同名称的模型,嵌套嵌套ngModel上面的示例也会创建一个新的数据模型。但是,当您使用点表示法时,将使JS查找范围的原型链。因此,如果它在当前作用域中找不到该值,它将尝试在父作用域中寻找它,依此类推。很少有其他指令可以创建不同的作用域,包括ngInclude和ngRepeat。希望现在清除。 :)

–AlwaysALearner
2014年6月13日在23:03



哪一个性能更好?我认为是ng-show和ng-hide吗?

–tom10271
15年8月3日,9:33

#2 楼

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

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

我在为当前客户建立的UI中观察并使用了它。整个用户界面非常拥挤,并且整个屏幕上都有ng-show和ng-hide。不必赘述,但我构建了一个通用组件,可以使用JSON配置对其进行管理,因此我必须在模板内部进行一些切换。存在一个ng-repeat,并且在ng-repeat内显示了一个表格,其中包含许多ng-show,ng-hide和ng-switch。他们希望在列表中显示至少50个重复,这将导致解决大约1500-2000条指令。我检查了代码,前面的Java后端+自定义JS将花费大约150毫秒来处理数据,然后Angular会在显示之前咀嚼2-3秒。客户没有抱怨,但是我感到震惊:-)

在搜索中,我偶然发现了ng-if指令。现在,也许最好指出,在构想此UI时,尚无ng-if。
因为ng-show和ng-hide中包含返回布尔值的函数,所以我可以轻松地用ng-if替换它们。这样,似乎不再评估所有内部指令。这意味着我回落到正在评估的所有指令中的大约三分之一,因此,UI加快了大约500毫秒-1秒的加载时间。 (我无法确定确切的秒数)

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

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

评论


是的,我想这是ng-if的目标:减少处理时间。当然,此指令的存在不仅取决于某些CSS伪选择器。好帖子! +1

–‐Bartłomiej Zalewski
2014年3月18日13:41

#3 楼

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

这在您要使用:first-child:last-child伪选择器进行样式设置时很有用。

评论


使用:first和:last选择器是什么意思?

–斯蒂芬·罗兰(Stephane Rolland)
13-10-4在10:26

糟糕,我的意思是:first-child和:last-child developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/ :最后一个孩子

–安德烈(Andrei)
13-10-4在10:43



#4 楼

@EdSpencer是正确的。如果您有很多元素,而仅使用ng-if实例化相关元素,则可以节省资源。
@CodeHater也很正确,如果您要经常删除并显示元素,则隐藏

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

#5 楼

关于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-show / hide,尽管这些元素不在屏幕上,它们仍然会存在并且验证将失败。所以ng-if营救您:)

–NeverGiveUp161
18年8月17日在10:14

#6 楼

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













你好柱塞!

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






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





在第一个列表中,内部/自身作用域中的on-click事件show变量已更改,但是ng-if正在监视外部作用域中同名的另一个变量,因此解决方案不起作用。在ng-show的情况下,我们只有一个show变量,这就是它起作用的原因。要修复首次尝试,我们应该通过show从父/外部范围引用$parent.show

#8 楼


-如果为false,将从DOM中删除元素。这意味着您所有附加到这些元素的事件和指令都将丢失。例如,用ng键单击子元素之一,当ng-if的值为false时,该元素将从DOM中删除,如果该元素为true,则再次创建该元素。
ng-show / ng-hide不会从DOM中删除元素。它使用CSS样式(.ng-hide)来隐藏/显示元素。这样,您的事件,附加到子项的指令就不会丢失。
ng-if在ng-show / ng-时创建子项范围隐藏不。


#9 楼

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 楼

需要注意的是,我现在发生了一件事情:
ng-show确实通过CSS隐藏了内容,是的,但是在div中应该是按钮的地方造成了奇怪的故障。

我有一个卡片,卡片的底部有两个按钮,根据实际状态,一个卡片可以与第三个(例如带有新条目的编辑按钮)交换。使用ng-show = false隐藏左按钮(在文件中第一个出现)时,碰巧以下按钮以卡的右边框结尾。
ng-if通过不包含以下代码来解决此问题全部。
(只需在这里检查是否使用ng-if而不是ng-show有一些隐藏的惊喜)

#11 楼

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

ngShow应用CSS规则隐藏/显示事物。

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

#12 楼

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

安全性

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

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

并且用大声喊叫来表示全部内容,被隐藏会被显示,这是安全漏洞。 :)

评论


这是一种极其脆弱的安全形式。如果内容是由服务器提供给客户端的,则您必须假定用户/攻击者可以访问它,而不管其是否存在于DOM中。服务器必须强制执行所有授权逻辑。

–tlrobinson
15年6月15日在18:04



考虑html而不是jsp ...现在,如果您想对html组件..i.e实施安全性。如果您想向用户隐藏某些组件...您将如何实现。以及如果您的配置分为后端的服务器端和前端的客户端。

– Ashish_B
15年6月16日在4:44