小编典典

在AngularJS中编写指令时,如何确定是否不需要新的作用域,新的子作用域或新的隔离作用域?

angularjs

我正在寻找一些指南,可以用来帮助确定编写新指令时要使用的范围类型。理想情况下,我想要类似于流程图的内容,该流程将引导我解决一系列问题并弹出正确的答案-
没有新的新作用域,新的子作用域或新的孤立作用域-但这可能要求太多。这是我目前微不足道的准则集:

  • 如果将使用指令的元素使用ng-model,请不要使用隔离范围。

  • 如果指令不修改任何范围/模型属性,请不要创建新的范围

  • 如果伪指令封装了一组DOM元素(文档中说“复杂的DOM结构”),并且该伪指令将用作元素,或者在同一元素上没有其他伪指令,则隔离作用域似乎工作良好。

我知道在某个元素上使用具有隔离范围的指令会强制同一元素上的所有其他指令使用相同的(一个)隔离范围,因此在可以使用隔离范围时这不会严格限制吗?

我希望Angular-UI团队中的一些人(或编写了许多指令的其他人)可以分享他们的经验。

请不要添加简单回答“对可重用组件使用隔离范围”的答案。


阅读 262

收藏
2020-07-04

共1个答案

小编典典

真是个好问题!我很 喜欢 听别人怎么说,但这里是我使用的指导方针。

高海拔前提:作用域用作我们在父控制器,指令和指令模板之间进行通信的“胶水”。

父范围: scope: false,因此完全没有新范围

我不经常使用它,但是正如@MarkRajcok所说,如果指令不访问任何范围变量(并且显然没有设置任何变量!),那么就我而言,这很好。这对于
在父指令的上下文中使用的子指令(尽管总是有例外)并且没有模板也很有用。基本上,带有模板的任何东西都不属于共享范围,因为您本质上是在为访问和操作公开该范围(但我敢肯定,此规则有例外)。

例如,我最近创建了一个指令,该指令使用我在编写过程中使用的SVG库绘制(静态)矢量图形。它有$observe两个属性(widthheight),并在计算中使用这些属性,但它既没有设置也没有读取任何范围变量,也没有模板。这是不创建另一个范围的好用例。我们不需要一个,那为什么要麻烦呢?

但是,在另一个SVG指令中,我需要使用一组数据,并且还必须存储一点点状态。在这种情况下,使用父级作用域是不负责任的(同样,通常来说)。所以与其…

子范围: scope: true

带有子作用域的指令是上下文感知的,旨在与当前作用域进行交互。

显然,相对于隔离范围而言,此方法的主要优势在于,用户可以自由地对想要的任何属性使用插值;例如,class="item-type-{{item.type}}"在具有隔离范围的指令上使用默认情况下将不起作用,但在具有子作用域的指令上可以正常使用,因为默认情况下仍可以在父作用域中找到内插的内容。同样,该指令本身可以在其自身范围内安全地评估属性和表达式,而不必担心父级污染或损坏。

例如,工具提示就是刚刚添加的内容;孤立范围将不起作用(默认情况下,请参见下文),因为期望我们在此使用其他指令或内插属性。工具提示只是一个增强。但是工具提示还需要在作用域上设置一些要与子指令和/或模板一起使用的东西,并且显然要管理其自身的状态,因此使用父作用域的确很不好。我们要么在污染它,要么在破坏它,布宜诺斯都没有。

我发现自己比隔离范围或父范围更经常使用子范围。

隔离范围: scope: {}

这是针对可重用组件的。:-)

但认真地说,我认为“可重用组件”是“自包含组件”。目的是将它们用于特定目的,因此将它们与其他指令结合或将其他内插属性固有地添加到DOM节点是没有意义的。

更具体地说,通过在父作用域的上下文中评估的指定属性,可以提供此独立功能所需的任何内容。它们可以是单向字符串(’@’),单向表达式(’&’)或双向变量绑定(’=’)。

在独立组件上,不需要在其上应用其他指令或属性,因为它本身就存在。它的样式由其自己的模板(如有必要)控制,并且可以包含适当的内容(如有必要)。它是独立的,因此我们将其放在一个单独的范围内也可以说:“不要对此烦恼。我通过这几个属性为您提供了已定义的API。”

最佳做法是从指令链接和控制器功能中排除尽可能多的基于模板的内容。这提供了另一个“类似于API”的配置点:指令的用户可以简单地替换模板!功能都保持不变,并且其内部API从未被使用过,但是我们可以根据需要尽可能地改变样式和DOM实现。ui
/ bootstrap是一个 很好的 例子,因为Peter&Pawel很棒。

隔离范围也非常适合与包含一起使用。带标签;它们不仅是全部功能,而且其 内部
的所有内容都可以在父范围内自由评估,同时让选项卡(和窗格)执行所需的任何操作。选项卡显然具有自己的 状态 ,该 状态
属于作用域(与模板进行交互),但是该状态与使用它的上下文无关-
它完全是使选项卡伪指令成为选项卡伪指令的内部。此外,在选项卡中使用任何其他指令没有太大意义。它们是选项卡-我们已经有了该功能!

将其包含更多功能或包含更多功能,但该指令已经存在。

综上所述,我应该注意,有一些方法可以解决隔离范围的某些限制(即功能),正如@ProLoser在他的回答中所暗示的那样。例如,在子作用域部分中,我提到了使用隔离作用域时(默认情况下)非定向属性中断时的插值。但是,例如,用户可以简单地使用class="item-type-{{$parent.item.type}}"它,它将再次起作用。因此,如果迫切需要在子作用域上使用隔离作用域,但您担心其中一些限制,请知道您可以在需要时解决所有这些限制。

摘要

没有新作用域的指令为只读;他们是完全值得信赖的(即应用程序内部的),并且它们不会碰插孔。具有子作用域的指令可 添加 功能,但它们不是 唯一的
功能。最后,隔离范围是针对整个目标的指令;它们是独立的,因此可以让它们无赖(大多数“正确”)。

我想打消我的初衷,但是当我想到更多事情时,我将对其进行更新。但这真是太糟糕了-这样的答案很久了…


PS:完全切线,但是由于我们在讨论范围,所以我更喜欢说“原型”,而其他人则更喜欢“原型”,这似乎更准确,但是根本无法奏效。:-)

2020-07-04