Angularjs属性绑定优先级

时间:2015-10-17 13:54:45

标签: javascript angularjs angularjs-directive isolate-scope

我们实施了下一个指令:

angular.module('app', [])
  .directive('dIsolatedWorks', function() {
    return {
      scope: {
        prop: '='
      },
      template: '<span>{{name}}: {{prop}}</span>',
      link: function(scope) {
        scope.name = 'isolated';
        scope.prop = 'link';
      }
    };
  })
  .directive('dIsolated', function() {
    return {
      scope: {
        prop: '@'
      },
      template: '<span>{{name}}: {{prop}}</span>',
      controller: function($scope) {
        $scope.prop = 'controller';
      },
      link: function(scope) {
        scope.name = 'isolated';
        scope.prop = 'link';
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div d-isolated-works prop="attribute"></div>
  <div d-isolated prop="attribute"></div>
</div>

实际上在实施过程中,我确信分配到scope.prop字段会更改变量,它将显示为'link',而不是'attribute'。 但目前我们看到真正的价值将是isolated: attribute。 但是,可以通过将字符串赋值更改为对象赋值来简单地修复它。

你能解释一下这种行为吗?

3 个答案:

答案 0 :(得分:1)

次要更改会产生与前缀=和@

相同的结果

angular.module('app', [])
.directive('dIsolatedWorks', function () {
return {
    scope: {
        prop: '='
    },
    template: '<span>{{name}}: {{prop}}</span>',
    link: function (scope) {
        scope.name = 'isolated';
        scope.prop = 'link';
    }
};
})
.directive('dIsolated', function ($timeout) {
return {
    scope: {
        prop: '@'
    },
    template: '<span>{{name}}: {{prop}}</span>',
    controller: function ($scope) {
        $scope.prop = 'controller';
    },
    link: function (scope, element, attr) {
        scope.name = 'isolated';
        $timeout(function(){  });
        $timeout(function(){
            console.log('Still I found attrib value: ',scope.prop);
          
          scope.prop = 'link'; // this will change it
            });
        //scope.prop = 'link';
    	
    }
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
    <div d-isolated-works prop="attribute"></div>
    <div d-isolated prop="attribute"></div>
</div>

但概念上

  

@ binding用于传递字符串。这些字符串支持{{}}   插值的表达式。例如: 。插值   表达式是根据指令的父范围进行评估的。

     

=绑定用于双向模型绑定。父范围中的模型链接到指令的隔离范围中的模型。改为一个   模型影响另一方,反之亦然。

通过牢记上述概念,分析:

1 - 当我们使用前缀'@'定义范围时,模板始终从attrib获取值(因此link scope.prop不会影响任何内容)

2 - 然后创建scope并为其分配attrib字符串值

但是

第二个摘要周期将在<{1}}或ng-clickng-model上运行时

3 - 它会改变值

4 - 在上面的代码中查看$timeout以便了解(运行它!)

快乐帮助!

答案 1 :(得分:0)

我相信隔离范围内的参数在链接阶段后绑定。这就是为什么你最终得到通过&#39; prop&#39;传递的价值的原因。属性,而不是您在链接功能中设置的属性。

无法在文档中找到它,就像我说的那样(https://docs.angularjs.org/guide/compiler),但做了一些证明了它的实验。

检查小提琴 - 我刚刚发起了&#39;属性&#39;父母范围内的财产和&#39; dIsolatedWorks&#39;类似于&#39; dIsolated&#39;

user 123456

http://jsfiddle.net/ndfqruxf/

为什么指令&#39; dIsolatedWorks&#39;正如您所期望的那样,因为在其上配置了双向绑定(&#39; =&#39;),但在名为&#39;属性&#39;的父作用域上没有变量。因此,&#39; dIsolatedWorks&#39;指令启动了变量。

答案 2 :(得分:0)

因此,在调查了angularjs代码以获得答案后,​​我找到了正确答案 - 根据angular.js v1.3.20,我们在@属性的链接函数中有下一行代码(第7698行):

      case '@':
            attrs.$observe(attrName, function(value) {
              isolateBindingContext[scopeName] = value;
            });
            attrs.$$observers[attrName].$$scope = scope;
            if (attrs[attrName]) {
              // If the attribute has been provided then we trigger an interpolation to ensure
              // the value is there for use in the link fn
              isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
            }
            break;

根据此代码

  1. Angularjs为属性注册$ observer(evalAsync因此它将在代码链结束后执行)
  2. 值从属性正确传播,因此我们会在链接函数中看到它的值
  3. 使用属性值传播链接功能。
  4. 链接功能更改道具价值并完成其工作
  5. 执行回到$ observer函数(因为它应该至少执行一次)
  6. $ observer被执行,它将值更改回属性值
  7. 因此,我们可以说指令体中字符串绑定参数的使用仅允许作为只读值,直到它被包装到超时块(或任何其他延迟执行)