7

我试图弄清楚为什么我无法覆盖通过隔离范围(@)传递给 angularJS 指令的值。我尝试vm.index用以下内容覆盖的值:

vm.index = parseInt(vm.index, 10)

但是,由于某种原因它不起作用。

如果我将其更改为:

vm.newIndex = parseInt(vm.index, 10)

有用。$scope此外,在作品 上分配价值。

为什么第一种方法不起作用?

我创建了这个示例 plunker以供参考。

4

2 回答 2

7

正如您@在此处使用的那样,它需要来自带有{{}}插值指令的属性的值。似乎指令首先被加载,然后vm.index值被评估。因此,在当前的摘要周期中没有发生变化。如果您希望反映这些内容,您需要使用 $timeout 以更安全的方式运行摘要循环。

$timeout(function(){
  vm.index = parseInt(vm.index, 10)
})

上面的事情是确保将值转换为十进制值。添加将发生在指令 html 上<h2>Item {{ vm.index + 1 }}</h2>

工作演示

这背后的可能原因

根据@dsfq 和我的讨论,我们通过了角度$compileAPI,发现它们是一种方法调用initializeDirectiveBindings,只有当我们controllerAs在具有隔离范围的指令中使用时才会调用。在这个函数中,有各种 binding 的 switch case@=&所以当你使用@这意味着调用 switch case 代码之后的一种绑定方式。

代码

case '@':
    if (!optional && !hasOwnProperty.call(attrs, attrName)) {
        destination[scopeName] = attrs[attrName] = void 0;
    }
    attrs.$observe(attrName, function(value) {
        if (isString(value)) {
            destination[scopeName] = value;
        }
    });
    attrs.$$observers[attrName].$$scope = scope;
    if (isString(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
        destination[scopeName] = $interpolate(attrs[attrName])(scope);
    }
    break;

在上面的代码中,您可以清楚地看到他们放置attrs.$observe了一种观察者,通常在值与插值时使用,就像在我们的例子中一样{{index}},这意味着$observe当摘要循环运行时会对其进行评估,这就是您需要的原因将值设为$timeout.indexdecimal

@dsfq 回答之所以有效,是因为他使用=了两种方式绑定,即代码不会让观察者直接从隔离范围中获取值,这里是代码。因此,如果没有摘要周期,该值就会更新。

于 2015-06-23T21:00:07.157 回答
6

index显然它与作用域值的单向绑定有关。因此 Angular 不会更新scope.index(或this.index在 的情况下bindToController: true),因为范围配置为

scope: {
    index: '@'
},

如果将其更改为双向绑定,例如:

scope: {
    index: '='
},

它将起作用:

<some-directive index="$index"></some-directive>

演示: http ://plnkr.co/edit/kq16cpk7gyw8IE7HiaQL?p=preview

升级版。@pankajparkar 提出了一个很好的观点,即在下一个摘要中更新值解决了这个问题。这种解决问题的方法比我在这个答案中所做的更接近。

于 2015-06-23T20:49:39.833 回答