gpt4 book ai didi

angularjs - Angular 表达式中的多个语句

转载 作者:行者123 更新时间:2023-12-04 11:39:33 25 4
gpt4 key购买 nike

我在玩 Angularjs,可能我在滥用它。我使用分号在这样的 Angular 表达式中包含多个语句( jsFiddle ):

<tr ng-repeat="i in [1, 2, 3, 4]">
<td>i = {{ m = k; k = j; j = i + 1; i}}</td>
<td>j = {{j}}</td>
<td>k = {{k}}</td>
<td>m = {{m}}</td>
</tr>

一开始我以为 k将具有 j 的值计算前 i+1 ,但显然它不是这样工作的。结果是:
i = 1   j = 2   k = 2   m = 2
i = 2 j = 3 k = 3 m = 3
i = 3 j = 4 k = 4 m = 4
i = 4 j = 5 k = 5 m = 5

所以显然分配 jkkm , 并不意味着值被复制,而是这些名称绑定(bind)在一起。我可以理解。但是如果我删除显示 k 值的行,就会发生一些奇怪的事情。 ( jsFiddle):
<tr ng-repeat="i in [1, 2, 3, 4]">
<td>i = {{ m = k; k = j; j = i + 1; i}}</td>
<td>j = {{j}}</td>
<td>m = {{m}}</td>
</tr>

我正在获得:
i = 1   j = 2   m =
i = 2 j = 3 m =
i = 3 j = 4 m =
i = 4 j = 5 m =

也就是说, m不包含任何值,尽管它绑定(bind)到 j (通过 k )。可能是因为 k本身不被评估。

我的问题是:这不是 AngularJS 中的错误吗?当然 k应该评估它是否在绑定(bind)链中,即使它没有直接显示。还是我误解了什么?

我知道这可能不是使用 AngularJS 的惯用方式,但我想真正了解表达式引擎,我无法解释这种行为。

最佳答案

这里有几个相互影响的问题。

首先,您的语句是倒序排列的:您在设置 j 之前设置 k=j,这导致它未定义。

其次,更重要的是,不应使用插值表达式(“{{}}”中的表达式)更改范围的状态 .这是有充分理由的:

插值和 watch

插值的工作方式是,当它编译你的 html 时, Angular 注册一个 scope.$watch在每个插值表达式上。

但是这些被监视的表达式可以在摘要期间多次执行:每当监听器修改范围时,它会导致 Angular 再次运行该范围上的监视。出于这个原因,被监视的表达式真的应该是“幂等的”:即,它们应该没有副作用/不会导致状态变化。这是来自documentation for $watch :

The watchExpression is called on every call to $digest() and should return the value which will be watched. (Since $digest() reruns when it detects changes the watchExpression can execute multiple times per $digest() and should be idempotent.)



跟踪示例

具体来说,这就是您的示例中发生的情况。首先,它与中继器无关。每个 ng-repeat item 有自己的范围,所以这里发生的事情等价于这个更简单的例子:
<div ng-app>
{{ i = 42 }}<br>
i = {{ m = k; k = j; j = i+1; i }}<br>
j = {{j}}<br>
k = {{k}}<br>
m = {{m}}<br>
</div>

(这里是 fiddle )

摘要是这样进行的:
  • 评估 {{ i = 42 }}scope.i到 42,并在文档中显示“42”。然而,由于范围已经改变,还有一个“”标志设置,这意味着我们将再次循环通过 watch (见下面的步骤5)
  • 评估 {{ m = k; k = j; j = i+1; i }}scope.mscope.kundefined , 和 scope.j到 43,并在文档中显示“42”。
  • 评估 {{ j }}在文档中显示“43”。
  • 评估 {{ k }}然后 {{ m }}两者都只是在文档中显示“”,因为它们当前未定义。
  • 现在,由于设置了脏标志,我们重复所有这些监视;这一次,当我们运行 {{ m = k; k = j; j = i+1; i }} , k = j 有效,因为 j 存在;所以 k 被赋值为 43。
  • 当我们回到 {{ k }}这一次,它的值从 undefined 变为 2,因此再次设置了脏标志,但现在文档显示“k = 2”。但是,{{ m }}仍然未定义。
  • 就像 5-6 一样,我们再次查看 watch ,这一次,{{ m = k; k = j; j = i+1; i }}导致 m 设置为 43。

  • Tangent:双处理 watch ?

    切线地,我在跟踪摘要代码时遇到了一件有趣的事情:似乎第一次通过 watch 时,脏标志总是设置为真,因为从未检查过的 watch 没有记录的“最后”值。似乎这会导致许多不必要的双重处理。即使观察值是像 {{2}} 这样的常量,这似乎也是正确的。我在这里误解了什么吗?

    关于angularjs - Angular 表达式中的多个语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17529644/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com