简体   繁体   English

AngularJS:指令隔离范围 - 范围变量undefined

[英]AngularJS: Directive isolate scope - scope variable undefined

Please, can someone explain me, why attrDir 's scope variable is visible, and oneWay 's not? 请,有人可以给我解释一下,为什么attrDir的范围变量是可见的, oneWay的不? I thought that scope: {} is isolated as well. 我认为scope: {}也是孤立的。

angular.module('test', []);

angular.module('test').directive('attrDir', attrDir);

function attrDir(){
    return {

        scope: true,

        link: function(scope){
          scope.hello = 'attrDir';
        }

    };
}

angular.module('test').directive('oneWay', oneWay);

function oneWay(){
    return {

        scope: {
          data: '<?'
        },

        link: function(scope){
          scope.hello = 'oneWay';  
        }

    };
}

hello will be rendered only in attr-dir . hello只会在attr-dir呈现。

<attr-dir>
  <span>{{hello}}</span>
</attr-dir>
<one-way>
  <span>{{hello}}</span>
</one-way>

Here is a plunker: https://plnkr.co/edit/2CM4vVRshWuJvaBj2q8T?p=preview 这是一个plunker: https ://plnkr.co/edit/2CM4vVRshWuJvaBj2q8T p = preview

Thx. 谢谢。

First, what you're observing has nothing to do with < binding. 首先,你所观察到的与<绑定无关。

The problem is that the expression {{hello}} inside both directives are not part of the template of these directives. 问题是两个指令的表达式{{hello}} 不是这些指令的模板的一部分。 And for such elements the rules for bindings are different. 对于这些元素,绑定规则是不同的。

Angular automatically creates link functions for {{hello}} expressions. Angular自动为{{hello}}表达式创建链接函数。 But the scopes against which these link functions are evaluated are different in your cases. 但是在这种情况下,评估这些链接函数的范围是不同的。

What you probably expected is this: 您可能期望的是:

            rootScope
         /             \
        /               \
attr-dir-new-scope  one-way-isoloate-scope
      /                   \
     /                     \
{{hello}}               {{hello}}

However, according to this comment in source : 但是,根据这篇评论来源

// We only pass the isolate scope, if the isolate directive has a template, //如果isolate指令有模板,我们只传递隔离范围,
// otherwise the child elements do not belong to the isolate directive. //否则子元素不属于isolate指令。

the real picture is this: 真实情况是这样的:

             root scope
         /             \    \
        /               \    \
attr-dir-new-scope       \    one-way-isoloate-scope
      /                   \
     /                     \
{{hello}}               {{hello}}

So in your example, the first directive <attr-dir> doesn't create isolate scope, but creates new scope, so when linking angular passes this new scope both to the linking function of your directive: 因此,在您的示例中,第一个指令<attr-dir>不会创建隔离范围,而是创建新范围,因此在链接角度时,将此新范围传递给指令的链接函数:

link: function(scope){
     scope.hello = 'attrDir';
}

and to the linking function created for the {{hello}} expression. 以及为{{hello}}表达式创建的链接函数。 That's why when you add a value in your linking function it's available in the expression linking function. 这就是为什么当你在链接函数中添加一个值时,它可以在表达式链接函数中使用。

But your second directive <one-way> creates isolate scope and according to the comment I mentioned above, the linking function of the directive gets isolated scope as it should, but the linking function of the expression receives different scope (root scope in your example). 但是你的第二个指令<one-way>创建了隔离范围 ,根据我上面提到的注释,指令的链接函数应该得到隔离范围 ,但表达式的链接函数接收不同的范围 (示例中的根范围) )。 So you're adding hello value on different scopes. 所以你要在不同的范围上添加hello值。 That's why the value is undefined. 这就是价值未定义的原因。

Both scope: true and scope:{} will create a child scope for the directive. 范围:true和范围:{}将为指令创建子范围。 But, 但,

scope:true will prototypically inherit the properties from the parent(say the controller where the directive comes under) where asscope:{} will not inherit the properties from the parent and hence called isolated scope:true将原型继承父级的属性(比如指令所在的控制器),其中asscope:{}不会从父级继承属性,因此称为隔离

As oneWay is an isolated scope directive and you are not passing the hello, so it is undefined in the HTML. 由于oneWay是一个独立的范围指令,并且您没有传递hello,因此它在HTML中未定义。

If scope is not specified, it is shared scope. 如果未指定范围,则为共享范围。 If scope is specified as true, it is inherited scope. 如果scope指定为true,则它是继承范围。 If scope is specified with curly braces, it is isolate scope. 如果使用花括号指定范围,则它是隔离范围。

The best way to visualize the scopes is by using console.log statements in your link functions like so, 可视化范围的最佳方法是在链接函数中使用console.log语句,如下所示,

link: function(scope) {          
      scope.hello = 'attrDir';
      console.log('scope in attrDir: ', scope);
    }

    link: function(scope) {          
          scope.hello = 'oneWay';
          console.log('scope in oneWay: ', scope);
        }

If you open the developer tools, you will see that the first directive inherits its parent scope in its prototype 如果打开开发人员工具,您将看到第一个指令在其原型中继承其父作用域

__proto__:Scope 

whereas the second one is an object with its own scope (by using curly braces you gave it an isolate scope) 而第二个是具有自己范围的对象(通过使用花括号,你给它一个隔离范围)

__proto__:Object

Because you're implementing component bindings in directive. 因为您正在指令中实现组件绑定。

The < symbol denotes one-way bindings which are available since 1.5. <符号表示从1.5开始可用的单向绑定。

If you want to show the hello in one-way component you should change the implementation like below: 如果要在one-way组件中显示hello ,则应更改实现,如下所示:

HTML HTML

 <one-way hello="$ctrl.hello">
      <span>{{$ctrl.hello}}</span>
    </one-way>

JS JS

angular.module('test').component('oneWay', {
  bindings:{
    hello:'='
  },
  controller: function() {
    this.hello = 'oneWay';
  }
});

Demo 演示

plnkr plnkr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM