Polymer dom-repeat not rendering changes with function as 项目
Polymer dom-repeat not rendering changes with function as items
在 Polymer 中,我使用一个函数来计算 dom-repeat
:
的项目
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
First: <span>[[item.first]]</span>
Last: <span>[[item.last]]</span>
</div>
</template>
但无论我尝试什么,当我更改 people
的子属性(例如 people.0.first
)时,我都无法让它呈现更新。对数组本身的更改有效(例如 this.push('people', ...)
)。可能我被 dirty check 击中了,在这种情况下我不知道如何覆盖它。
完整示例:
<body fullbleed unresolved>
<widget-example></widget-example>
<dom-module id="widget-example">
<template>
<div style="color: red;">Why doesn't rename first person cause a visible change?</div>
<div>First 4 people:
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
First: <span>[[item.first]]</span>
Last: <span>[[item.last]]</span>
</div>
</template>
</div>
<div>
<!-- Why doesn't this work? -->
<button on-tap="renameFirstPerson">Rename first person</button>
<button on-tap="sendFrontToBack">Send front to back</button>
</div>
</template>
<script>
Polymer({
is: "widget-example",
properties: {
people: {
type: Array,
value: () => [
{'first': 'Joe', 'last': 'Blogs'},
{'first': 'Jon', 'last': 'Bigs'},
{'first': 'John', 'last': 'Doe'},
{'first': 'Josh', 'last': 'Blo'},
],
},
},
observers: [
'o(people.*)',
],
o: function(change) {
console.log('o', change)
},
first4People: function() {
console.log('first4People called');
return this.people.slice(0, 4);
},
renameFirstPerson: function() {
console.log('before sendFrontToBack', this.people)
this.set(['people.0.first'], this.people[0].first+'Foo');
// None of this causes the rename to show up.
var person = this.people[0];
this.people[0] = {};
this.people[0] = person;
this.notifyPath('people.0');
this.set('person', {});
this.set('person', person);
var people = this.get('people');
this.set('people', []);
this.set('people', people);
},
sendFrontToBack: function() {
console.log('before sendFrontToBack', this.people)
var last = this.shift('people', this.people);
this.push('people', last);
console.log('after sendFrontToBack', this.people)
},
});
</script>
</dom-module>
</body>
</html>
Polymer 1.x 这种工作有点奇怪,在 2.0 中应该工作得更好,但现在你必须清空然后重写整个数据数组以重新评估更改。出于某种原因,如果您这样做仍然没有任何反应,但如果您在新框架中提供新值,那么它就会开始工作:
// Save the data locally
let peoples = this.people;
// Do the change in the local array
peoples[0].first += 'Foo';
// Empty the data so it can reevaluate
this.people = []; // this.set('people', []);
// Insert the new data in a new frame
requestAnimationFrame(time => {
this.people = peoples; // this.set('people', peoples);
});
这是正确的解决方案:Plunk
缺少的是:
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
Index: <span>[[index]]</span>
<br>
First as this:[[arrayItem(people.*, index, 'first')]]
<br>
First not as this: <span>[[item.first]]</span>
</div>
<br><br>
</template>
相似:
这里的具体问题涉及使用计算绑定为 items
属性 创建匿名数组。当您使用 set
更改 sub属性 时,重新计算计算的绑定,但 people.0
object 没有更改,因此当 dom-repeat
遍历数组,脏检查告诉它对象没有改变。
并且 dom-repeat
不知道对 people.0.first
的更改与其 items
属性 有关,因此它不会以这种方式进行更改, 要么。
修复它以替换 people.0
对象,如下所示:
renameFirstPerson: function() {
// create a new object to defeat dirty-check.
var updated = Object.assign({}, this.people[0]);
updated.first = updated.first + 'Foo';
// swap the new object in with 'set', so the observer gets called.
this.set('people.0', updated);
}
您可以在此处采用其他一些方法,但其中 none 非常简单。希望这会有所帮助。
在 Polymer 中,我使用一个函数来计算 dom-repeat
:
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
First: <span>[[item.first]]</span>
Last: <span>[[item.last]]</span>
</div>
</template>
但无论我尝试什么,当我更改 people
的子属性(例如 people.0.first
)时,我都无法让它呈现更新。对数组本身的更改有效(例如 this.push('people', ...)
)。可能我被 dirty check 击中了,在这种情况下我不知道如何覆盖它。
完整示例:
<body fullbleed unresolved>
<widget-example></widget-example>
<dom-module id="widget-example">
<template>
<div style="color: red;">Why doesn't rename first person cause a visible change?</div>
<div>First 4 people:
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
First: <span>[[item.first]]</span>
Last: <span>[[item.last]]</span>
</div>
</template>
</div>
<div>
<!-- Why doesn't this work? -->
<button on-tap="renameFirstPerson">Rename first person</button>
<button on-tap="sendFrontToBack">Send front to back</button>
</div>
</template>
<script>
Polymer({
is: "widget-example",
properties: {
people: {
type: Array,
value: () => [
{'first': 'Joe', 'last': 'Blogs'},
{'first': 'Jon', 'last': 'Bigs'},
{'first': 'John', 'last': 'Doe'},
{'first': 'Josh', 'last': 'Blo'},
],
},
},
observers: [
'o(people.*)',
],
o: function(change) {
console.log('o', change)
},
first4People: function() {
console.log('first4People called');
return this.people.slice(0, 4);
},
renameFirstPerson: function() {
console.log('before sendFrontToBack', this.people)
this.set(['people.0.first'], this.people[0].first+'Foo');
// None of this causes the rename to show up.
var person = this.people[0];
this.people[0] = {};
this.people[0] = person;
this.notifyPath('people.0');
this.set('person', {});
this.set('person', person);
var people = this.get('people');
this.set('people', []);
this.set('people', people);
},
sendFrontToBack: function() {
console.log('before sendFrontToBack', this.people)
var last = this.shift('people', this.people);
this.push('people', last);
console.log('after sendFrontToBack', this.people)
},
});
</script>
</dom-module>
</body>
</html>
Polymer 1.x 这种工作有点奇怪,在 2.0 中应该工作得更好,但现在你必须清空然后重写整个数据数组以重新评估更改。出于某种原因,如果您这样做仍然没有任何反应,但如果您在新框架中提供新值,那么它就会开始工作:
// Save the data locally
let peoples = this.people;
// Do the change in the local array
peoples[0].first += 'Foo';
// Empty the data so it can reevaluate
this.people = []; // this.set('people', []);
// Insert the new data in a new frame
requestAnimationFrame(time => {
this.people = peoples; // this.set('people', peoples);
});
这是正确的解决方案:Plunk
缺少的是:
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
<div>
Index: <span>[[index]]</span>
<br>
First as this:[[arrayItem(people.*, index, 'first')]]
<br>
First not as this: <span>[[item.first]]</span>
</div>
<br><br>
</template>
相似:
这里的具体问题涉及使用计算绑定为 items
属性 创建匿名数组。当您使用 set
更改 sub属性 时,重新计算计算的绑定,但 people.0
object 没有更改,因此当 dom-repeat
遍历数组,脏检查告诉它对象没有改变。
并且 dom-repeat
不知道对 people.0.first
的更改与其 items
属性 有关,因此它不会以这种方式进行更改, 要么。
修复它以替换 people.0
对象,如下所示:
renameFirstPerson: function() {
// create a new object to defeat dirty-check.
var updated = Object.assign({}, this.people[0]);
updated.first = updated.first + 'Foo';
// swap the new object in with 'set', so the observer gets called.
this.set('people.0', updated);
}
您可以在此处采用其他一些方法,但其中 none 非常简单。希望这会有所帮助。