一尘不染

为什么不能覆盖这样的变量的值?

angularjs

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

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

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

如果我将其更改为:

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

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

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

我已经创建了这个示例插件


阅读 234

收藏
2020-07-04

共1个答案

一尘不染

如您@在此处使用的那样,需要通过{{}}插值指令从属性获取值。似乎指令首先被加载,然后vm.index值被求值。因此,在当前摘要周期中不会发生更改。如果希望这些内容得到反映,则需要使用$
timeout以更安全的方式运行摘要循环。

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

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

工作演示

这背后的可能原因

根据@dsfq和我的讨论,我们遍历了angular
$compile
API,发现它们是一个方法调用
initializeDirectiveBindings

,仅当我们controllerAs在具有隔离范围的in指令中使用时才调用。在这个功能有开关的情况下的各种结合@=并且&,这样你使用@,这意味着一个双向绑定下面的开关情况下的代码被调用。

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在创造index价值的同时投入decimal

@dsfq答案之所以有效,是因为他使用=了提供两种方式的绑定,这些代码不会使观察者直接从隔离的范围中获取值,
这是代码

。因此,没有摘要循环,该值将被更新。

2020-07-04