【问题标题】:Angular Templates - inline expressions vs calling to functionAngular Templates - 内联表达式与函数调用
【发布时间】:2018-06-13 04:45:40
【问题描述】:

这两者有什么区别:

<li [ngClass]="{disabledField: condition1 && condition2 && condition3}">Click</li>

<li [ngClass]="{disabledField: shouldDisableField()}">Click</li>

在组件类中:

shouldDisableField(): boolean{
  return this.condition1 && this.condition2 && this.condition3;
}

【问题讨论】:

  • 优雅和简洁的方式是使用getter而不是函数get shouldDisableField: boolean { return this.condition1 &amp;&amp; this.condition2 &amp;&amp; this.condition3 }&lt;li [class.disabledField]="shouldDisableField"&gt;Click&lt;/li&gt;
  • my answer有什么不清楚的地方吗?
  • @AngularInDepth.com 不,非常明确的答案。

标签: javascript angular angular5


【解决方案1】:

这里的大多数答案只提到性能差异是微不足道的。 我不认为这是正确的,这里的表现可能很重要。 请参阅 Phil Parsons 的精彩文章: Function calls in Angular expressions are killing your apps performance

您应该注意那里显示的性能损失

【讨论】:

  • 这里还有人为因素:当它被重构为组件内部的一个函数时,开发人员更有可能在其中放置更多的逻辑、扩展的逻辑或繁重的逻辑,只是偶然,因为他们正在寻找进入组件代码,并没有查看它在模板中的使用方式。特别是如果有人将函数标记为private(d'oh)。虽然放一些小逻辑没问题,但粗放或重逻辑很可能会扼杀性能。随着此类问题的累积,效果会随着源代码的生命周期而增长/叠加。
【解决方案2】:

唯一的区别是函数调用和评估表达式在 JavaScript 中,Angular 在这里是无关紧要的。函数调用通常稍微慢一些,所以第一个选项应该稍微快一些。

Angular 视图编译器为updateRenderer 函数生成以下代码:

function(_ck, _v) {
    var _co = _v.component;
---> var currVal_0 = _ck(_v, 3, 0, ((_co.condition1 && _co.condition2) && _co.condition3));
    _ck(_v, 2, 0, currVal_0);
}

function(_ck, _v) {
    var _co = _v.component;
--> var currVal_0 = _ck(_v, 3, 0, _co.shouldDisableField());
    _ck(_v, 2, 0, currVal_0);
}

如您所见,只有一行不同,这才是最重要的。

您可以在文章中阅读更多关于updateRenderer函数的信息:

【讨论】:

  • 这里还有人为因素:当它被重构为组件内部的一个函数时,开发人员更有可能在其中放置更多的逻辑、扩展的逻辑或繁重的逻辑,只是偶然的,因为他们正在寻找进入组件代码,并没有查看它在模板中的使用方式。特别是如果有人将函数标记为private(d'oh)。虽然放一些小逻辑没问题,但粗放或重逻辑很可能会扼杀性能。随着此类问题的累积,效果会随着源代码的生命周期而增长/叠加。
  • @quetzalcoatl,是的,没错。如果您需要可重用的逻辑,可能最好的方法是将其放入a pure pipe
【解决方案3】:

并非如此,尽管我建议使用第二种方法,因为这样更简洁,并且有助于最大限度地减少模板中的数据传输。诚然,这可能看起来微不足道,但它是划分 javascript 代码的好习惯,而且它将获得代码缩小和 gzip 的好处(如果在 HTTP 请求上启用)。

但是,如果这是一个例外情况,那么第一个可能对其他开发人员(或您自己)更有帮助,但我只会在极少数情况下使用它,因为第二个给你更容易更新/扩展/修复它的能力,特别是如果您可能重复使用相同的规则/条件。

关于 Angular 的绑定模型,我不确定是否有很多缓存方式(如果您是这样想的话)或我个人看到的性能。

希望对您有所帮助。

【讨论】:

  • 是的,我更多地关注缓存(如果存在)和性能问题。使用函数会不会产生很小的开销?
  • 归结为javascript引擎中的堆栈空间,在您的情况下,这不值得担心。我见过一个案例,我让一些开发人员在一个表列表上运行 for-loop,添加一个 click 事件处理程序,每次都会在其中创建函数声明,这会杀死浏览器。 (例如,for(var index in tablerowbuttons) tablerowbuttons[index].onclick = function(evt) { ...some function... } 用数千个函数定义抽取了堆栈空间)不知道 V8 现在是如何处理它们的,但糟糕的做法永远不会少。
  • 旁注:如果您由于范围界定而需要为每个项目创建一个函数,我建议您使用所需范围数据的参数创建一个通用函数,然后使用function.bind 方法。 (例如,这是一个俗气的例子,但给出了总体思路。elm.onclick = handlerfunc.bind(elm, scopevar1, scopevar2, ...)function handlerfunc(scopevar1, scopevar2, event) { ...
【解决方案4】:

如上述答案所述,这两种方法都可以正常工作。

<li [ngClass]="{disabledField: condition1 && condition2 && condition3}">Click</li> 

<li [ngClass]="{disabledField: shouldDisableField()}">Click</li> 

但也有一些不同之处。

其中最重要的事情之一是 AOT 策略。在从 JIT 迁移到 AOT 时,函数调用可能会让人头疼(大多数开发人员都会遇到这种情况)。如果调用的函数是私有函数,AOT 编译会抛出编译时错误,因为它将模板和组件视为 2 个不同的实体。

另外一点是,数据绑定是可读的,容易理解的。

话虽如此,我们可能会遇到一种情况,仅靠数据绑定无法解决问题。在这些情况下调用函数不会是错误的做法!

希望对您有所帮助! :)

【讨论】:

    【解决方案5】:

    其实并没有什么不同。我会用

    <li [ngClass]="{disabledField: condition1 && condition2 && condition3}">Click</li> 
    

    如果我的模板中只有一个这样的表达式。否则我会使用

    <li [ngClass]="{disabledField: shouldDisableField()}">Click</li> 
    

    减少编写的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-14
      • 2020-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 2018-11-29
      • 1970-01-01
      相关资源
      最近更新 更多