48

请在此处查看示例

foodMeApp.directive('fmRating', function() {
  return {
    restrict: 'E',
    scope: {
      symbol: '@',
      max: '@',
      readonly: '@'
    },
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {

      attrs.max = scope.max = parseInt(scope.max || 5, 10);
...

Angular 需要在隔离范围对象中定义symbol,以从父范围访问它。maxreadonly

它在这里使用

<fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"></fm-rating>

那么,这样做的目的是attrs什么?无法访问通过的所有属性attrs。为什么不能一个访问 max asattrs.max而不是scope.max

为什么要分配回来 like attrs.max = scope.max

由于这个应用程序是由 Angular 作者编写的,我希望有一个理由。

谢谢。

4

2 回答 2

95

attrs 的目的是什么?

在与指令相同的元素上定义的属性有几个目的:

  1. 它们是将信息传递到使用隔离范围的指令的唯一方法。由于指令隔离作用域在原型上不是从父作用域继承的,因此我们需要一种方法来指定要传递给隔离作用域的内容。因此,“对象哈希”中的“@”、“=”和“&”都需要一个属性来指定要传递的数据/信息。
  2. 它们用作指令间通信机制。(例如,独立管理独立 AngularJS 指令之间的通信
  3. 他们规范化属性名称。

不能访问通过 attrs 传递的所有属性吗?

是的,你可以,但是

  1. 你不会有任何数据绑定。
    '@' 设置单向“字符串”数据绑定(父作用域 → 指令隔离作用域) 使用 @ 您在指令中看到/获取的值始终是字符串,因此如果您尝试传递反对你的指令。
    '=' 设置双向数据绑定(父范围 ↔ 指令隔离范围)。
    如果没有数据绑定,您的指令将无法 $watch 或 $observe 自动更改模型/数据。
  2. 带有 s 的属性值{{}}会给你带来问题,因为它们不会被插值。
    假设我们有<my-directive name="My name is {{name}}">并且父作用域有$scope.name='Mark'. 然后,在链接函数内部,console.log(attrs.name)结果为undefined.
    如果 name 是使用“@”定义的隔离范围属性,则attrs.$observe('name', function(val) { console.log(val) })结果为My name is Mark. (请注意,在链接函数内部,必须使用 $observe() 来获取插值。)

为什么不能将 max 的一个值访问为 attrs.max 而不是 scope.max

上面回答了

为什么要像 attrs.max = scope.max 一样分配回去?

我能想到这样做的唯一原因是,以防某些其他指令需要查看此属性/值(即指令间通信)。但是,另一个指令需要在该指令之后运行才能使其工作(可以通过priority指令设置在一定程度上进行控制)。

摘要:在具有隔离范围的指令中,通常您不想使用attrs. (我想这可能是一种将初始化数据/值发送到指令中的方法——即,如果您不需要这些值的数据绑定并且不需要插值。)

于 2013-01-14T16:44:22.740 回答
3

使用 attrs 您可以访问 html 标签中定义的属性,例如

<fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true">

因此,在这种情况下,您将可以访问symbolreadonly属性。您在自定义指令中定义的每个属性都可用于attrs变量。

块:

attrs.max = scope.max = parseInt(scope.max || 5, 10);

解析并将当前scope.max值或5(如果不存在)分配给 scope.max 和 attrs.max。这样,在分配之后,您可以从 attrs.max 中读取。在此之前 attrs.max 属性未定义。

检查 fmRating.js 源我不知道为什么/在哪里/何时使用这段代码。

于 2013-01-13T12:06:17.893 回答