我有一个带有一系列对象的模型。对象具有用户可以更新的属性。
在UI的另一部分,我想展示一些关于数组的统计数据;项目总数和设置属性的项目数。
使用单数组而不是对象的示例。单击列表项以切换" a"财产:http://jsfiddle.net/rskqbquL/4/
<polymer-element name="test-cool">
<template>
<ol>
<template repeat="{{item, i in list}}">
<li on-tap="{{onTap}}" x-index="{{i}}">{{item[0]}}</li>
</template>
</ol>
<p>Total: {{list.length}}</p>
<p>A:s: {{list | countA}}</p>
</template>
<script>
Polymer("test-cool", {
list: [["a"], ["ab"], ["ac"], ["d"], ["e"]],
countA: function(list) {
var ret = 0;
list.forEach(function(item) {
if (item[0].indexOf("a") >= 0) ++ret;
});
return ret;
},
onTap: function(e, _, el) {
var item = el.innerText;
var index = parseInt(el.getAttribute("x-index"));
if (item.indexOf("a") >= 0) {
this.list[index][0] = item.slice(1);
} else {
this.list[index][0] = "a" + item;
}
// Workaround
this.list = this.list.slice();
}
});
</script>
</polymer-element>
<test-cool></test-cool>
我找不到任何方法来观察数组中所有项的特定属性,因此onTap()中的列表的解决方法是虚拟赋值。
收集有关数组子集的统计信息的惯用聚合物方式是什么?
答案 0 :(得分:0)
使用过滤器并勾选list
(例如1this.list = this.list.slice()) works, but every time the
on-tap handlers gets called, the entire DOM list is rendered. Instead, I would create a
counterA`变量以跟踪数组长度
此外,而不是使用:
var item = el.innerText;
var index = parseInt(el.getAttribute("x-index"));
您可以直接使用数据模型(docs):
var item = el.templateInstance.model.item;
var index = el.templateInstance.model.i;
解决此问题的一种方法是http://jsbin.com/fitav/1/edit:
<p>A:s: {{countA}}</p>
onTap: function(e, detail, el) {
var item = el.templateInstance.model.item;
var index = el.templateInstance.model.i;
this.list[index][0] = this.hasA(item[0]) ?
item[0].slice(1) : "a" + item;
this.countA = this.filterA();
},
hasA: function(item) {
return item.indexOf("a") >= 0;
},
listChanged: function() {
this.countA = this.filterA();
}
答案 1 :(得分:0)
目前的最佳做法是使用观察踢来触发重新计算。 Fwiw,我们通常对这个答案不满意,并正致力于更好的自动化。
开局就是这样描述你的装订:
<p>A:s: {{list | countA(kick)}}</p>
并且在更改列表项的关键位置,递增kick
属性。需要说明的是,kick
属性除了触发重新计算外没有任何其他用途。
kick: 0,
onTap: function(e) {
var item = e.target.templateInstance.model.item;
item[0] = this.toggleA(item[0]);
this.kick++;
}
正如我所说,这是一个临时解决方案,直到我们进行更多自动化变更检测或至少提供一个api来踢。
答案 2 :(得分:0)
这是使用我最近为此目的编写的Polymer元素的解决方案:<observe-array-items>
。 <observe-array-items>
简化了为数组中的每个项创建/维护PathObserver
的过程。
<script src="//www.polymer-project.org/platform.js"></script>
<link rel="import" href="//www.polymer-project.org/components/polymer/polymer.html">
<link rel="import" href="//rawgit.com/jeffposnick/observe-array-items/master/observe-array-items.html">
<polymer-element name="array-observation">
<template>
<observe-array-items array="{{list}}"
path="text"
on-array-item-changed="{{handleArrayItemChanged}}">
</observe-array-items>
<ol>
<template repeat="{{item in list}}">
<li on-tap="{{handleListTap}}">{{item.text}}</li>
</template>
</ol>
<p>
<input type="text" value="{{newItemText}}">
<button on-tap="{{handleAddItem}}">Add Item</button>
</p>
<p>Total: {{list.length}}</p>
<p>'A's: {{countOfA}}</p>
</template>
<script>
Polymer({
countOfA: 0,
list: null,
newItemText: 'f',
listChanged: function() {
// This will be triggered when list is first initialized,
// and any time an item is added or removed from the array.
var count = 0;
this.list.forEach(function(item) {
if (this._hasA(item.text)) {
count++;
}
}.bind(this));
this.countOfA = count;
},
_hasA: function(str) {
console.log('checking', str);
return str.indexOf('a') >= 0;
},
handleArrayItemChanged: function(e) {
if (!this._hasA(e.detail.oldValue) && this._hasA(e.detail.newValue)) {
// If the old value didn't have an 'a' and the new value does, then increment countOfA.
this.countOfA++;
} else if(this._hasA(e.detail.oldValue) && !this._hasA(e.detail.newValue)) {
// If the old value did have an 'a' and the new value doesn't, then decrement countOfA.
this.countOfA--;
}
// Don't do anything for the other cases, since 'a'-ness has stayed the same.
},
handleListTap: function(e, _, el) {
var item = el.templateInstance.model.item;
if (this._hasA(item.text)) {
item.text = item.text.slice(1);
} else {
item.text = 'a' + item.text;
}
},
handleAddItem: function() {
this.list.push({text: this.newItemText});
},
ready: function() {
this.list = [
{text: 'a'},
{text: 'ab'},
{text: 'ac'},
{text: 'd'},
{text: 'e'}
];
}
});
</script>
</polymer-element>
<h1>Polymer Demo: Observing Changes to Properties of Items in an Array</h1>
<array-observation></array-observation>
&#13;
我认为这是解决您尝试做的事情的一种相当惯用的方式,因为它在很大程度上依赖于观察回调来确保相关状态保持最新。您可以直接从代码中的任何位置修改数据,而无需担心忘记调用特定的帮助函数等。