0

我们实施了下一个指令:

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. 但是,可以通过将字符串分配更改为对象分配来简单地修复它。

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

4

3 回答 3

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 用于传递字符串。这些字符串支持插值的 {{}} 表达式。例如: 。插值表达式根据指令的父范围进行评估。

= binding 用于双向模型绑定。父作用域中的模型链接到指令的隔离作用域中的模型。对一个模型的更改会影响另一个模型,反之亦然。

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

1 -当我们用前缀'@'定义范围时,模板总是从属性中获取值(所以linkscope.prop 没有任何影响)

2 -然后创建scope并分配属性字符串值给它

3 -当第二个摘要循环运行时(on ng-clickor ng-modelor $timeout)它会改变值

4 -请参阅$timeout上面的代码以了解(运行它!)

乐于助人!

于 2015-10-17T16:16:36.680 回答
0

我相信隔离范围内的参数在链接阶段之后绑定。这就是为什么你最终得到通过“prop”属性传递的值,而不是你在链接函数中设置的值。

就像我说的(https://docs.angularjs.org/guide/compiler)在文档中找不到,但做了一个小实验证明了这一点。

检查小提琴 - 我刚刚在父范围内启动了“属性”属性,“dIsolatedWorks”的工作方式类似于“dIsolated”

<div ng-app="app">
    {{attribute = 'hello world';}}

    <div d-isolated-works prop="attribute"></div>
    <div d-isolated prop="attribute"></div>
</div>

http://jsfiddle.net/ndfqruxf/

指令“dIsolatedWorks”按预期工作的原因是因为在其上配置了两种方式绑定(“=”),但父作用域上没有名为“属性”的变量。因此,“dIsolatedWorks”指令启动了该变量。

于 2015-10-17T15:43:49.400 回答
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 并将值更改回属性值

因此,我们可以说指令正文中字符串绑定参数的使用只允许作为只读值,直到它被包装到超时块(或任何其他延迟执行)

于 2015-10-17T19:39:43.780 回答