【问题标题】:Confuse about the AngularJS scope when multiple directives share same element当多个指令共享同一个元素时,对 AngularJS 范围感到困惑
【发布时间】:2015-06-11 00:51:20
【问题描述】:

全部:

我是 AngularJS 指令作用域的新手,我想知道当多个独立作用域指令分配给同一个元素时 AngularJS 如何处理作用域。

例如:

app.controller("main", function($scope){
    $scope.data = [
        {
            id:"id_1"
        },
        {
            id:"id_2"
        },
        {
            id:"id_3"
        },
        {
            id:"id_4"
        }
    ];
});

app.directive("isodir", function(){
    return {
        restrict:"AE",
        scope: {},
        controller: function($scope){$scope.d = {id:"isodir_id"} },
        link: function(scope, EL, attrs){}
    }
});

HTML部分是:

<isodir ng-repeat="d in data track by $index">{{d.id}}</isodir>

<isodir>{{d.id}}</isodir>

让我很困惑的主要有两个问题:

[1] 对于 html 部分[1]:带有 ng-repeat 的那个,谁能给我 关于如何 AngularJS 决定使用谁的范围的一些解释,因为 ng-repeat 和 isodir 都是孤立的范围(根据结果, 但事实证明,ng-repeat 范围被应用了,我想知道为什么 未应用 isodir);有时,如果我使用两个指令都带有隔离 作用域,AngularJS 会报错。 但是 ng-repeat 不报告 错误。

[2] 对于 html 部分[2]:没有 ng-repeat 的部分,让我们说我 毫无疑问地接受关于 part[1] 的事实,那么这意味着 ng-repeat 范围内的 d 被渲染到 {{d.id}},但在部分 [2], 我在 isodir 控制器中定义了 $scope.d,但是 为什么 这个 d 可以 用作 {{d.id}}

的值

谢谢

【问题讨论】:

  • 1) ng-repeat 绝对不使用隔离范围。 2) 隔离作用域不继承任何父作用域,并且不得共享
  • @Phil 您能否更详细地解释在我的示例中启动 angularJS 时整个过程是如何运行的?

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

1) 这将与 $compile 顺序有关,其中优先级较高的指令将首先执行。 ngRepeat 的优先级为 1000,高于自定义指令的 0。 但是对于您的情况,这是由于您使用的 ng-bind-html {{d.id}} 不适用于自定义指令,因为您有一个隔离范围,因此它期望 {{d.id}} 将被绑定在内部指令模板而不是它之外。即使用模板或模板Url。

检查 1st plunkr,它是你的指令的固定版本

app.directive('isodir', function(){
return {
    restrict:"AE",
    priority: 0,
    template: "{{d.id}}",
    scope: {},
    controller: function($scope){$scope.d = {id:"isodir_id"} }
}
});

http://plnkr.co/edit/3noKzbJGMav7MBozW4i0?p=preview

如您所见,结果是 isodir,因为它是最新编译的,因此会覆盖 ng-repeat d 范围。

将其与 2nd plunkr 进行比较,哪个自定义指令具有比 ngRepeat 更高的优先级

app.directive('isodir', function(){
return {
    restrict:"AE",
    priority: 100000,
    template: "{{d.id}}",
    scope: {},
    controller: function($scope){$scope.d = {id:"isodir_id"} }
}
});

http://plnkr.co/edit/1RhF0LpvfBOaVPZju6Fr?p=preview

如您所见,ng-repeat 覆盖 {{d.id}} 以使用 ngRepeat 范围对象。

2) 如上所述,这是由于孤立的范围。如果您想在没有模板/模板 URL 的自定义指令中使用 {{d.id}},那么您必须删除隔离范围。

【讨论】:

  • 感谢您的解释,这很有帮助(虽然不是完全理解,但有基本的想法)。我想验证一件事:Phil 给了我一个答案,“ng-repeat 最肯定不使用隔离范围”,我对此不确定,我认为它创建了隔离范围并使用无论 ng-bin- html 或 transclude 以获取其中的 DOM,我错了吗?
  • 当我玩第一个 plunkr 时,我发现有趣的一件事是:如果我从自定义目录中删除模板属性,{{d.id}} 将返回到 id_1、id_2、id_3 ...我对此的理解是:如果指令具有模板属性,它将清除内部的所有内容,只将模板放在那里并从其范围绑定变量(如果它是隔离范围,在我的情况下,{{d. html 中的 id}} 实际上已被永久删除并由我模板中的 {{d.id}} 替换,它们不一样。对吧?)
  • 如果没有模板属性,指令会限制它的范围而不删除里面的东西,当$compile遇到html中的{{d.id}}时,它不知道那里是来自 isodir 的范围,但只有 ng-repeat 范围是最接近访问的,所以它呈现来自 ng-repeat 的值?如果这通常是正确的,我想知道 ng-repeat 允许其范围如何影响 html 中的变量(我认为它使用与 isodir 相同的结构格式,但为什么它会影响其中的变量,因为它可以复制其中的内容作为它的模板?)?
  • ng-repeat 不使用隔离作用域,而是使用 transclude。是的,模板将替换您的内部 html 内容。 ng-repeat 能够翻译内部 html 中的 {d.id},因为它没有使用隔离范围。指令中的隔离范围是 scope : {} ,正如您在 github.com/angular/angular.js/blob/master/src/ng/directive/… 中看到的那样,ngRepeat 不使用隔离范围。
  • 谢谢,我会尝试更多的例子来理解这一点。
猜你喜欢
  • 2017-01-17
  • 1970-01-01
  • 2014-07-08
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多