如何理解angularjs中指令的scope属性?

时间:2017-05-05 06:55:38

标签: javascript angularjs angularjs-scope directive

在angularjs指令的指南教程中,指令对象可以具有scope属性。它定义了指令的范围。

虽然范围属性值可能为true,但以下是对范围的解释:( link of the scope definition

  

true:原型继承自其父级的新子范围   将为指令的元素创建。 如果有多个指令   同一个元素请求一个新范围,只创建一个新范围。

我对大胆风格的句子感到困惑。多个指令如何在同一个元素上使用相同的范围?

2 个答案:

答案 0 :(得分:1)

据我所知,这意味着每个元素都会创建范围而不是每个指令。

因此,范围将自动在指令之间共享,而不会创建每个指令的不同副本。

此链接https://www.bennadel.com/blog/2729-don-t-blindly-isolate-all-the-scopes-in-angularjs-directives.htm

他们提到过:

如果你正在使用AngularJS 1.2,那么下一个障碍就是你不能将两个isolate-scope指令应用于同一个元素。看看下面的代码。它所做的就是将两个指令应用于同一个元素。并且,指令只执行隔离范围。

因此,如果在两个指令中使用相同的范围变量,则会抛出以下错误

  

错误:错误:multidir

     

多指令资源争用

     

多个指令[bnThat,bnThis]要求新的/隔离范围

因此,对于这种情况,嵌套方式的transclusion或place指令可以完成这项工作。

上面提到的示例在下面的代码段中给出。



// Create an application module for our demo.
var app = angular.module("Demo", []);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I request an isolate scope directive.
app.directive(
  "bnThis",
  function() {
    // Return the directive configuration. Notice that we are creating an
    // isolate scope, even though we are not binding any expressions.
    return ({
      link: angular.noop,
      restrict: "A",
      scope: {}
    });
  }
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I request an isolate scope directive.
app.directive(
  "bnThat",
  function() {
    // Return the directive configuration. Notice that we are creating an
    // isolate scope, even though we are not binding any expressions.
    return ({
      link: angular.noop,
      restrict: "A",
      scope: {}
    });
  }
);

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="Demo">

  <p bn-this bn-that>
    Look at the console output.
  </p>

</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

我们不知道在使用我们的指令时范围将包含什么。 因此,为我们的指令提供明确定义的公众是一种很好的做法 面对界面。这可确保指令不会依赖或受其影响 使用它的范围内的任意属性。 我们的指令及其模板中使用的范围有三个选项。这个 在指令定义中定义:
•从使用窗口小部件的位置重用范围。这是 默认值,对应范围:false。

•创建子范围,原型继承自范围 使用小部件。您可以使用范围指定它:true。

•创建一个独立的范围,它不是原型继承的,所以它是 完全与其父母隔离。您可以通过传递对象来指定它 scope属性:scope:{...}。 我们希望将我们的小部件模板与其余部分完全分离 应用程序,这样两者之间就没有数据泄露的危险。

注意: - [虽然隔离范围不是从其父级原型继承的, 它仍然可以通过$ parent属性访问其父级的范围。 但这被认为是一种不好的做法,因为你正在破坏 指令与周围环境隔离。]

由于我们的范围现在与父范围隔离,我们需要显式映射 父范围和隔离范围之间的值。这是通过引用完成的 AngularJS表达式出现在指令所在元素的属性上。 在我们的分页指令的情况下,num-pages和current-page属性 履行这个职责。 我们可以将这些属性中的表达式与属性同步 模板范围通过手表。我们可以手动设置,也可以询问 AngularJS为我们连线。我们可以指定三种类型的接口 元素属性和隔离范围之间:插入(@),数据 bind(=)和表达式(&amp;)。您可以将这些接口指定为键值对 指令定义的scope属性。 关键是隔离范围上的字段名称。该值是@,=或&amp;之一 后跟元素上属性的名称:

scope: {
 isolated1: '@attribute1',
 isolated2: '=attribute2',
 isolated3: '&attribute3'
}

这里我们在隔离范围上定义了三个字段,AngularJS将映射它们 指令出现的元素上指定属性的值。

注意: [如果值中省略了属性名称,则假定为 该属性与隔离范围字段具有相同的名称: 范围:{isolated1:'@'} 它期望该属性被称为isolated1。]

使用@插值属性 @符号表示AngularJS应插入指定的值 属性并在更改时更新隔离的scope属性。插值是 与{{}}花括号一起使用,以使用父作用域中的值生成字符串。 注意: - [常见错误是期望插值对象成为对象 本身。插值始终返回一个字符串。所以如果你有一个对象,比如说 user有一个名为userName的字段,然后插入{{user}} 将用户对象转换为字符串,你将无法 访问字符串上的userName属性。]

此属性插值等效于手动$观察属性:

attrs.$observe('attribute1', function(value) {
 isolatedScope.isolated1 = value;
});

attrs。$$ observers ['attribute1']。$$ scope = parentScope; 使用=将数据绑定到属性 =符号表示AngularJS应该将表达式保留在指定的表达式中 属性和隔离范围上的值彼此同步。这是双向的 数据绑定,允许对象和值直接映射到内部 在小部件之外。 由于此接口支持双向数据绑定,因此给出了表达式 在属性中应该是可分配的(也就是说,指的是一个字段) 范围或对象)而不是任意计算表达式。 这种绑定有点像设置两个$ watch函数:

var parentGet = $parse(attrs['attribute2']);
var parentSet = parentGet.assign;
parentScope.$watch(parentGet, function(value) {
 isolatedScope.isolated2 = value;
});
isolatedScope.$watch('isolated2', function(value) {
 parentSet(parentScope, value);
});

实际实现更复杂,以确保两个范围之间的稳定性。 在中提供回调表达式 属性与&amp; &amp; symbol表示元素属性中提供的表达式 将作为一个函数在范围上可用,当被调用时,将执行 表达。这对于从窗口小部件创建回调很有用。 建立自己的指令 这个绑定相当于$解析属性中的表达式并公开 在隔离范围内解析表达式函数:

parentGet = $parse(attrs['attribute3']);
scope.isolated3 = function(locals) {
    return parentGet(parentScope, locals);
};