【问题标题】:Detect array mutation检测阵列突变
【发布时间】:2016-04-04 16:47:34
【问题描述】:

我制作了一个简单的概念验证 Polymer 1.0 应用程序来演示我的问题:JSBin

在我的问题中,我使用array mutation methods 来更改包含购物项目列表的数组。

但是,这似乎没有按预期工作。我确实dom-repeat 和打印数组长度时得到了更改。 但是当我打印数组本身或将其包装在函数中时,我没有收到更改事件。

简而言之,为什么会这样?

<p>Number of items: [[list.length]]</p>

为什么这不起作用

<p>Items inline: [[list]]</p>    
<p>Observe function : [[_observe(list)]]</p>

另外,当我取消注释以下行(在 JSBin 中)时,事情似乎像 indened 一样工作。但我不喜欢它,因为它有点 hackish。

app.notifyPath('list', app.list.slice());

我通过阅读此问题偶然发现了slice() 修复:https://github.com/Polymer/polymer/issues/2068


编辑

因此,在查看了 cmets 之后,“这是设计使然”这个问题的答案是肯定的。数组本身不会改变(因为它只是一个引用),但它的属性 do 会改变。这就是slice() 强制重新加载的原因,因为它创建了一个浅拷贝。

然而,人们可能会争论这是否可行。是的,变量list 不会改变本身。但是将[[list]] 放入HTML 代码实际上会触发toString()。并且那个函数的结果已经改变了。

我想我现在只能捎带length 属性...

【问题讨论】:

  • 你的 jsbin 示例在 chrome 中对我来说很好用
  • 如果你想知道为什么观察者没有被触发,那只是因为链接到对象它只是链接,并没有改变,观察list.length并返回列表
  • 或者您可以在某个 var 中备份指向数组的链接,不带第二个参数进行通知,并使用 backedUp 列表立即通知,我不确定哪个更快,但这种方法不需要克隆数组,等等复杂情况下不需要深度克隆。
  • 其他解决方案(如果您更改数组值)可能是设置通知对象,每次更新数组时都需要更改值,您不能只看整个数组或任何其他对象的属性或子属性值,只是因为在一般情况下它会很慢

标签: javascript arrays polymer-1.0 mutation


【解决方案1】:

正如在 cmets 中提到的,notifyPathslice 调用正在创建数组的浅表副本并将不同的引用分配回 list 变量 - 触发绑定更新。如果不维护一个单独的 (watchable) 变量或搞乱对象引用,我能想到的唯一其他解决方法是搭载 list.length 属性而不是列表本身并通过它某种“格式化”功能。 例如

<p>Items inline: [[format(list.length)]]</p>
app.format = function(){
    return app.list.toString();
};

» Fiddle


正如@zb 所指出的,您可以对此进行扩展,并通过将相关变量作为参数也传递给任何数组来使函数可重用:

<p>Items inline: [[format(list, list.length)]]</p>
app.format = function(list){
    return list.toString();
};

» Fiddle

【讨论】:

  • 是的,我想这会使它可以重复使用。无论如何,这有点杂乱无章,用例相当有限。
  • @zb' 和 @Emissary 我稍微更新了我的问题。但这可能不会改变问题的解决方案:搭载length 属性。
猜你喜欢
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2015-05-26
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多