为啥我不能像这样覆盖变量的值?
Posted
技术标签:
【中文标题】为啥我不能像这样覆盖变量的值?【英文标题】:Why can't I overwrite the value of a variable like this?为什么我不能像这样覆盖变量的值? 【发布时间】:2015-09-09 20:27:53 【问题描述】:我试图弄清楚为什么我无法覆盖通过隔离范围 (@
) 传递给 angularJS 指令的值。我尝试用以下内容覆盖vm.index
的值:
vm.index = parseInt(vm.index, 10)
但是,由于某种原因,它不起作用。
如果我将其更改为:
vm.newIndex = parseInt(vm.index, 10)
它有效。此外,在 $scope
上分配值也可以。
为什么第一种方法不起作用?
我创建了这个example plunker 以供参考。
【问题讨论】:
你说它“不起作用”到底是什么意思? 对不起,我的意思不是vm.index
不会从字符串转换为数字,这会在执行 vm.index + 1
之类的操作时导致字符串连接。
@brso05,我知道。但是,范围不是问题,因为您可以通过将vm.index = ...
更改为vm.newIndex = ...
并更新模板以使用vm.newIndex + 1
来验证自己。
@RaphaelRafatpanah 你能看看我更新的答案吗..这会让你更清楚为什么vm.index
不能通过直接从控制器直接parseInt
工作
插件链接已失效。
【参考方案1】:
正如您在此处使用的@
,它需要来自带有 插值指令的属性的值。似乎指令首先被加载,然后
vm.index
值被评估。因此,在当前的摘要周期中没有发生变化。如果您希望反映这些内容,您需要使用 $timeout 以更安全的方式运行摘要循环。
$timeout(function()
vm.index = parseInt(vm.index, 10)
)
最重要的是确保将值转换为十进制值。添加将发生在指令 html <h2>Item vm.index + 1 </h2>
Working Demo
这背后的可能原因
根据@dsfq 和我的讨论,我们通过了角度$compile
API,发现它们是一种方法调用initializeDirectiveBindings
,只有当我们在具有隔离范围的指令中使用controllerAs
时才会调用它。在此函数中,有各种绑定 @
、=
和 &
的 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
,这意味着这个@987654340 @ 在摘要循环运行时被评估,这就是为什么您需要将 $timeout
设置为 index
值作为 decimal
。
@dsfq 回答之所以有效,是因为他使用=
提供了两种方式绑定,即代码不会让观察者直接从隔离范围here is the code 中获取值。因此,如果没有摘要循环,该值将得到更新。
【讨论】:
这是解决问题的正确方法。发生的情况是控制器在 指令范围配置扩展之前被初始化。所以控制器首先运行,然后 scope => index 从属性值创建控制器的 this.index ,这是一个字符串。它会覆盖您在控制器中设置的任何内容。【参考方案2】:显然它与作用域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
UPD。 @pankajparkar 提出了一个很好的观点,即在下一个摘要中更新值解决了这个问题。这种解决问题的方法比我在这个答案中所做的更接近。
【讨论】:
对不起。但我认为你误读了这个问题。为什么范围的事情有效而vm.index
事情不工作,我的意思是在指令 html 上添加 ..
是的,看起来你是对的,但不清楚为什么在这种情况下需要下一个摘要。
这可能是因为@
或者我可以说插值指令..指令首先被初始化&在解析器评估后填充值
是的,它肯定与@
有关,但在这种情况下我不确定整个机器。但是你提出了一个很好的超时问题。
感谢您的赞赏..您的解决方案也很酷..但没有解释 OP 的问题答案..以上是关于为啥我不能像这样覆盖变量的值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用类变量的这段代码不能像在 Java 中那样工作? [复制]
为啥我不能更改 Timer.scheduledTimer 函数中变量的值?
为啥我不能像传递其他变量一样将函数从 Express.js 传递给 EJS?