我正在学习聚合物。一个挑战我的项目是更新数组的项目。我希望有一个聚合物CDN,这样我就可以把小提琴放在一起了。不过现在,我有一个定义如下的元素:
my element.html
<dom-module id="my-element">
<button on-click="onLoadData">Load Data</button>
<button on-click="onTest1Click">Test 1</button>
<button on-click="onTest2Click">Test 2</button>
<template is="dom-repeat" items="[[ data ]]" as="element">
<div><span>[[ element.id ]]</span> - <span>[[ element.status ]]</span></div>
<template is="dom-repeat" items="[[ element.children ]]" as="child">
<div> <span>[[ child.id ]]</span> - <span>[[ child.status ]]</span></div>
</template>
</template>
</template>
<script>
Polymer({
is: 'my-element',
properties: {
data: {
type: Array,
value: function() {
return [];
}
}
},
onLoadData: function() {
// Generate some dummy data for the sake of illustration.
for (var i=1; i<=3; i++) {
var element = {
id: i,
state: 'Initialized',
description: ''
};
element.children = [];
for (var j=1; j<=5; j++) {
var child = {
id: i + '-' + j,
state: 'Initialized',
description: ''
}
element.children.push(child);
}
data.push(element);
}
},
// Setting an individual property value works
onTest1Click: function() {
this.set('data.0.children.0.state', 'data set');
},
// Setting an entire object value does NOT work.
onTest2Click: function() {
var c = this.data[0].children[0];
c.state = 'data set';
this.set('data.0.children.0', c);
}
});
</script>
</dom-module>
出于某种原因,如果我更新数组元素的属性值(如onTest1Click
所示),则UI将正确更新。但是,如果我更新整个元素(如onTest2Click
所示),则UI不会得到更新。在我的实际问题中,我正在更新一个元素的多个属性。因此,我尝试更新数组元素,而不仅仅是属性。我是做错了什么还是误解了什么?或者,我是否必须单独更新每个属性值?
如果您想突变数组,而不仅仅是数组中的一个对象(例如交换掉数组中的整个元素),有类似于this.set
的数组突变方法。
例如,this.splice('data.0.children', 0, 1, c)
将删除子数组0索引处的当前项,并将其替换为新项,这似乎是您正在尝试执行的操作。还有this.shift
、this.unshift
、this.push
和this.pop
。这些都与它们的Array原型相似。
需要注意的一点是,在您的示例中,您实际上也没有交换出整个对象。当您从数组中获取元素,对字段进行变异,并尝试将其替换为自身时,实际上并不是在替换它,因此这实际上不会触发更新。由于该字段的突变是在Polymer的通知系统之外进行的,因此也不会触发更新。如果将项目替换为实际的不同对象,它将使用拼接工作。https://jsbin.com/rapomiyaga/1/edit?html,输出(这是Günter Zöchbauer的jsbin的修改快照)
如果您没有复制对象/创建一个全新的对象,则需要通过this.set
单独更新每个字段。
是的,您需要单独更新每个属性值。当您调用set
时,Polymer将转到给定的路径并检查该值是否已更改。如果值是一个对象,它将比较引用(而不是子属性)。由于对象引用没有更改,因此不会更新UI。