何时支持 ng-if 与 ng-show/ng-hide?

Posted

技术标签:

【中文标题】何时支持 ng-if 与 ng-show/ng-hide?【英文标题】:When to favor ng-if vs. ng-show/ng-hide? 【发布时间】:2014-03-19 02:55:51 【问题描述】:

我了解ng-showng-hide 会影响元素上设置的类,而ng-if 控制是否将元素呈现为DOM 的一部分。

是否有关于选择 ng-if 而不是 ng-show/ng-hide 或反之亦然的指南?

【问题讨论】:

what is the difference between ng-if and ng-show/ng-hide 的可能重复项 与dart 语言无关。 【参考方案1】:

取决于您的用例,但总结一下区别:

    ng-if 将从 DOM 中删除元素。这意味着您的所有处理程序或附加到这些元素的任何其他内容都将丢失。例如,如果您将点击处理程序绑定到子元素之一,当 ng-if 评估为 false 时,该元素将从 DOM 中删除,并且您的点击处理程序将不再工作,即使在 ng-if 稍后评估为 true 并且显示元素。您需要重新附加处理程序。 ng-show/ng-hide 不会从 DOM 中删除元素。它使用 CSS 样式来隐藏/显示元素(注意:您可能需要添加自己的类)。这样,您的附加到孩子的处理程序就不会丢失。 ng-if 创建子作用域,而 ng-show/ng-hide 没有

ng-show/ng-hide 相比,使用ng-if 时,不在DOM 中的元素对性能的影响较小,并且您的Web 应用程序可能看起来更快。根据我的经验,差异可以忽略不计。当同时使用ng-show/ng-hideng-if 时,动画是可能的,Angular 文档中都有这两个示例。

最终,您需要回答的问题是您是否可以从 DOM 中删除元素?

【讨论】:

您可以将 CSS3 动画与 ng-if 一起使用。检查动画段落和docs 中的示例。同样对于ng-hide/ng-show:first-child:nth-child 等css 选择器将无法正常工作,因为隐藏的元素也会被计算在内。 angular.dart 中的动画服务相对较新。在撰写本文时,它不可用。 如果您使用指令(如 ng-click)来绑定处理程序,那么您的第一点不是问题,因为您应该这样做。 另外,ng-if 会创建一个新范围,而 ng-show 不会。 还应该提到的是,如果频繁地在 DOM 中添加和删除元素会产生很高的性能成本。【参考方案2】:

请参阅 here 了解 CodePen,它演示了 ng-if/ng-show 工作方式的差异,DOM 方式。

@markovuksanovic 很好地回答了这个问题。但我会从另一个角度来看:我总是使用ng-if 并将这些元素从 DOM 中取出,除非:

    出于某种原因,您需要元素上的数据绑定和$watch-es 在它们不可见时保持活动状态。如果您希望能够检查当前不可见的输入的有效性,以确定整个表单是否有效,那么表单可能是一个很好的例子。 如上所述,您正在使用带有条件事件处理程序的一些非常精细的有状态逻辑。 也就是说,如果您发现自己手动附加和分离处理程序,以至于在使用 ng-if 时丢失了重要状态,请问问自己该状态是否可以更好地在数据模型中表示,并且每当呈现元素时,处理程序由指令有条件地应用。换句话说,处理程序的存在/不存在是状态数据的一种形式。将这些数据从 DOM 中取出,并放入模型中。处理程序的存在/不存在应由数据确定,因此易于重新创建。

Angular 写得非常好。考虑到它的作用,它很快。但它所做的是一大堆魔法,让困难的事情(比如 2 路数据绑定)看起来非常简单。让所有这些事情看起来很容易需要一些性能开销。您可能会惊讶地发现,在$digest 循环中,一个 setter 函数被评估了数百次或数千次,而这块 DOM 甚至没有人在看。然后你意识到你有几十个或几百个不可见的元素都在做同样的事情......

桌面可能确实足够强大,可以解决大多数 JS 执行速度问题。但是,如果您正在为移动设备开发,那么在人为可能的情况下使用 ng-if 应该是不费吹灰之力的。 JS 速度在移动处理器上仍然很重要。使用 ng-if 是一种非常简单的方法,可以以非常非常低的成本获得潜在的显着优化。

【讨论】:

对上述答案的补充非常好。给出一些好的上下文,这也有助于决策。谢谢。 ng-show 在你有的时候很有用,比如每个标签都有很多需要时间渲染的内容。在第一次渲染之后,选项卡之间的移动将是即时的,而ng-if 需要重新渲染、绑定事件等。正如你所说的,缺点是创建在后台执行的手表。 Angular 迫切需要ng-ifshowwatch【参考方案3】:

ng-if on ng-include 和 on ng-controller 会有很大的影响 在 ng-include 上,它不会加载所需的部分,并且除非标志为真,否则不会处理 在 ng-controller 上,除非标志为真,否则它不会加载控制器 但问题是当一个标志在 ng 中为假时,如果它会从 DOM 中删除,当标志恢复为真时,它将重新加载 DOM,在这种情况下,ng-show 更好,一次显示 ng-if 更好

【讨论】:

【参考方案4】:

一个重要提示:

ngIf(与 ngShow 不同)通常会创建可能产生意外结果的子作用域。

我遇到了一个与此相关的问题,我花了很多时间来弄清楚发生了什么。

(我的指令将其模型值写入错误的范围。)

所以,为了节省你的头发,除非你跑得太慢,否则只需使用 ngShow。

无论如何,性能差异几乎不明显,我还不确定谁会在没有测试的情况下受到青睐......

【讨论】:

ngIf 内的数据绑定中使用 $parent.scopevar 将纠正使用 ngIf 时出现的子范围问题 这并不完全正确(原始@user2173353 的评论,即)。如果你坚持良好的做法,你就不会惹上麻烦。这是一个非常基本的规则:“如果没有点,那么你做错了”。有关其工作原理的演示,请参见此处:bit.ly/1SPv4wL。另一个很好的参考(见错误#2):bit.ly/1QfFeWd >(我的指令将其模型值写入错误的范围。)这是不坚持上述做法的结果。 @piotr.d 你是对的,但这不是初学者可能需要关注的事情,还有另一个最佳实践表明最好将性能改进留到最后(尤其是性能改进可能不是现实中的改进)。我已经看到人们把ngIf 放在任何地方,他们相信这会提高性能。这根本不是真的,如果没有在特定情况下进行测试或深入分析,就不能说哪个最好,ngIfngShow。所以,我仍然建议忘记ngIf,直到看到表现不佳或知道自己在做什么 好点。但是使用 controllerAs 使得这不是问题。例如,请参阅John Papa's take on controllerAs and vm。【参考方案5】:

根据我的经验:

1) 如果您的页面有一个使用 ng-if/ng-show 来显示/隐藏某些内容的切换,那么 ng-if 会导致更多的浏览器延迟(更慢)。例如:如果你有一个用于在两个视图之间切换的按钮,ng-show 似乎更快。

2) ng-if 将在评估为真/假时创建/销毁作用域。如果您有一个控制器附加到 ng-if,则每次 ng-if 评估为 true 时都会执行该控制器代码。如果您使用 ng-show,控制器代码只会执行一次。因此,如果您有一个可以在多个视图之间切换的按钮,那么使用 ng-if 和 ng-show 将对您编写控制器代码的方式产生巨大的影响。

【讨论】:

说的太对了! ng-if 不一定会让你的前端更快。这取决于您的需求。实际上,如果您在错误的情况下使用它可能会反过来。 但根据我的说法,ng-if 不会渲染到 DOM 上,因此与 ng-show/hide 相比它更快。我错了吗,请让我纠正一下。 ng-if 如果评估为 false 会更快,因为正如您所说,不需要将任何内容插入 DOM。但是,如果它是真的,那么您需要将 - 可能非常复杂的 - 元素插入到 DOM 中。 "2) ng-if 在计算结果为 true/false 时将创建/销毁范围。如果您有一个控制器附加到 ng-if,则该控制器代码将在每次“ 【参考方案6】:

如果您使用ng-show or ng-hide,则无论表达式的值如何,内容(例如来自服务器的缩略图)都将被加载,但将根据表达式的值显示。

如果您使用ng-if,则仅当 ng-if 的表达式计算结果为真时才会加载内容。

在您要从服务器加载数据或图像并仅根据用户交互显示这些数据或图像的情况下,使用 ng-if 是一个好主意。这样一来,您的页面加载就不会被不必要的 nw 密集型任务阻塞。

【讨论】:

这特别有用,因为即使 CSS 隐藏了它们的 DOM 容器,大多数浏览器也会加载图像。他们通常只寻找img 标签的src 属性,当它出现时它会被加载!【参考方案7】:

答案并不简单:

这取决于目标机器(移动设备还是桌面设备),取决于数据的性质、浏览器、操作系统、运行它的硬件……如果您真的想知道,您需要进行基准测试。

这主要是内存与计算的问题...与大多数性能问题一样,对于列表之类的重复元素 (n),差异可能会变得显着,尤其是在嵌套时(nxn,或更糟)以及您在其中运行什么样的计算这些元素:

ng-show:如果这些可选元素经常出现(密集),例如 90% 时间,让它们准备好并且只显示/隐藏它们可能会更快,特别是如果它们的内容很便宜(只是纯文本,无需计算或加载)。这会消耗内存,因为它会用隐藏元素填充 DOM,但仅仅显示/隐藏已经存在的东西对浏览器来说可能是一种廉价的操作。

ng-if:相反,如果元素可能不会显示(稀疏),则只需实时构建并销毁它们,尤其是如果它们的内容获取成本很高(计算/排序/过滤,图像,生成的图像)​​。这对于稀有或“按需”元素来说是理想的,它在不填充 DOM 方面节省了内存,但可能会花费大量计算(创建/销毁元素)和带宽(获取远程内容)。它还取决于您在视图中的计算量(过滤/排序)与模型中已有的计算量(预排序/预过滤的数据)。

【讨论】:

技术事实的其他答案。此为智慧。先生,您显然已经构建了非平凡的 Angular 应用程序! +1 这个问题超越了角度问题,它是计算机科学中的一个基本问题,从某一点来看,一种方法比另一种方法更有效。通常这可以通过一些基准测试找到。因此,您甚至可以根据项目数在一种方法和另一种方法之间切换...类似主题:math.stackexchange.com/questions/1632739/…

以上是关于何时支持 ng-if 与 ng-show/ng-hide?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS ng-if 与 'f' 和 'F' 的问题

组件绑定与 findComponent() - 何时使用哪个?

何时使用 f:viewAction / preRenderView 与 PostConstruct?

Angular ng-if不重新编译指令

Angular ng-if 没有按预期响应

Angular面试题