我试图了解 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 中预定义,并将显示样式设置为无(使用 !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-if 指令是所有 Angular 指令中最高(如果不是最高)优先级之一。这意味着:它将在所有其他优先级较低的指令之前先运行。它首先运行的事实意味着在处理任何内部指令之前有效地删除了该元素。或者至少:这就是我所做的。
我在为当前客户构建的 UI 中观察并使用了它。整个 UI 非常紧凑,上面有 ng-show 和 ng-hide。不再赘述,但我构建了一个通用组件,可以使用 JSON 配置对其进行管理,因此我必须在模板内部进行一些切换。存在一个 ng-repeat,在 ng-repeat 内部显示了一个表格,其中有很多 ng-shows、ng-hides 甚至 ng-switches。他们希望在列表中显示至少 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
指令从页面中删除内容,ng-show/ng-hide
使用 CSS display
属性隐藏内容。
如果您想使用 :first-child
和 :last-child
伪选择器来设置样式,这很有用。
:first-child
和 :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/: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.
原因是输入字段存在并且它是 required
但由于它是隐藏的 Chrome 无法专注于它。这实际上会破坏您的代码,因为此错误会停止脚本执行。所以要小心!
@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}}
事实上,与 ng-show
不同的是,ng-if
指令创建了自己的范围,这导致了有趣的实际差异:
angular.module('app', []).controller('ctrl', function($scope){ $scope.delete = function(array, item){ array.splice(array.indexOf(item), 1); } })
在第一个列表中,来自 innner/own 范围的 on-click
事件、show
变量已更改,但 ng-if
正在监视来自 outer 范围的另一个变量同名,所以解决方案不起作用。在 ng-show
的情况下,我们只有一个 show
变量,这就是它起作用的原因。要修复第一次尝试,我们应该通过 $parent.show
从父/外部范围引用 show
。
ng-if if false 将从 DOM 中删除元素。这意味着您的所有事件、附加到这些元素的指令都将丢失。例如,ng-click 到其中一个子元素,当 ng-if 评估为 false 时,该元素将从 DOM 中删除,并且当它为 true 时再次重新创建。 ng-show/ng-hide 不会从 DOM 中移除元素。它使用 CSS 样式 (.ng-hide) 来隐藏/显示元素。这样您的事件、附加到子级的指令就不会丢失。 ng-if 创建一个子作用域,而 ng-show/ng-hide 没有。
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-show 确实通过 css 隐藏了内容,是的,但是它导致了 div 应该是按钮的奇怪故障。
我有一张底部有两个按钮的卡片,根据实际状态,一个与第三个交换,例如带有新条目的编辑按钮。使用 ng-show=false 隐藏左边的按钮(文件中的第一个)碰巧下面的按钮以卡片外的右边框结束。 ng-if 完全不包含代码来解决这个问题。 (如果使用 ng-if 而不是 ng-show 有一些隐藏的惊喜,请在这里检查)
ngIf 通过删除或重新创建元素对 DOM 进行操作。
而 ngShow 应用 css 规则来隐藏/显示事物。
对于大多数情况(并非总是),我将其总结为,如果您需要一次性检查来显示/隐藏内容,请使用 ng-if
,如果您需要基于显示/隐藏内容在屏幕上的用户操作(例如选中复选框然后显示文本框,取消选中然后隐藏文本框等),然后使用 ng-show
ng-if 和 ng-show 的一个有趣区别是:
安全
ng-if 块中存在的 DOM 元素在其值为 false 的情况下不会被渲染
在 ng-show 的情况下,用户可以打开您的 Inspect Element Window 并将其值设置为 TRUE。
随着一声呐喊,本应隐藏的全部内容被显示出来,这是一个安全漏洞。 :)
不定期副业成功案例分享
ng-if
删除 HTML 元素本身,由ng-model
添加的模型不再存在。data.input
中有一个对象时它如何/为什么工作......但模型中单独的data
不起作用。 @CodeHaterngIf
创建一个新范围,因此查看嵌套ngModel
上面的示例将创建一个新data
模型,即使父范围中存在同名模型。但是当你使用点符号时,你会让 JS 查找作用域的原型链。所以如果它在当前范围内没有找到该值,它会尝试在父范围内寻找它,依此类推。很少有其他创建不同范围的指令是ngInclude
、ngRepeat
。希望现在清楚。 :)