dom-重复filter/sort重绘错误
dom-repeat filter/sort redraw error
我对 dom-repeat
重绘的方式有疑问。下面的代码片段演示了过滤和排序简单的对象数组可能会向最终用户错误地呈现数据。
我确定这与 _applyFullRefresh
方法 (https://github.com/Polymer/polymer/blob/master/src/lib/template/dom-repeat.html#L482) 中的实例重用有关。
我能够修改此方法以通过重用具有匹配密钥的实例来创建有效的解决方案。可以在这里看到一个差异:https://github.com/Polymer/polymer/compare/master...TomK:patch-1
我的问题: dom-repeat
的补丁是否是我实现工作示例的唯一方法?
片段预期结果:
选择 filter/sort 的任意组合后,一行中的两个数字(item content
和 x-item content
)应始终相同。
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="basic polymer jsbin">
<meta charset="utf-8">
<base href="//polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id="x-item-test">
<template>
x-item content: [[_innerText]]
</template>
<script>
HTMLImports.whenReady(
function ()
{
Polymer(
{
is: 'x-item-test',
properties: {
_innerText: {type: String}
},
attached: function ()
{
Polymer.RenderStatus.afterNextRender(this, this.__updateProp.bind(this));
new MutationObserver(this.__updateProp.bind(this))
.observe(this, {childList: true, subtree: true, characterData: true});
},
__updateProp: function ()
{
var nodes = this.getEffectiveChildNodes(), output = '';
for(var i in nodes)
{
var n = nodes[i];
if(n.nodeType == 3 && n.nodeValue)
{
output += n.nodeValue;
}
}
this._innerText = output;
}
}
);
}
);
</script>
</dom-module>
<dom-module id="test-app">
<template>
<div>
Filter <input type="checkbox" checked="{{_applyFilter::change}}">
</div>
<div>
Sort <input type="checkbox" checked="{{_reverse::change}}">
</div>
<template is="dom-repeat" items="[[actions]]" filter="{{_filter(_applyFilter)}}" sort="{{_sort(_reverse)}}">
<div>Item content: [[item.id]] -
<x-item-test>[[item.id]]
<div>ignored</div>
</x-item-test>
</div>
</template>
</template>
<script>
HTMLImports.whenReady(
function ()
{
Polymer(
{
is: 'test-app',
properties: {
actions: {
type: Array,
value: [{id: '1', primary: true}, {id: '2'}, {id: '3', primary: true}, {id: '4'}]
},
_applyFilter: {type: Boolean, value: false},
_reverse: {type: Boolean, value: false}
},
_filter: function (applyFilter)
{
return function (item)
{
return !applyFilter || item.primary;
}
},
_sort: function (reverse)
{
return function (a, b)
{
if(reverse)
{
return a.id < b.id
}
return a.id >= b.id;
}
}
}
);
}
);
</script>
</dom-module>
</head>
<body>
<test-app></test-app>
</body>
</html>
在 Polymer 1.x 中,由于 dom-repeat
重用实例的方式,我认为没有好的方法可以完成您想要做的事情。
执行 属性 绑定而不是将光 DOM 子级传递给 x-item-test
将是在 1.x 中执行此操作的最佳方法。
对每个数组项进行实例查找是 O(n^2) 我认为这对于一般情况来说是不可接受的。
如果出于某种原因你真的需要使用 light DOM children,我能想到的最后一个(相当可怕的)选项是有一个遍历模板实例的 dom-change 监听器并对它们调用一些更新方法。
我无法想象任何比 属性 绑定更可取的用例,但有时我不是很有想象力。
我在 2.0 预览版中没有看到这个问题:
http://jsbin.com/vuritog/2/edit?html,output
希望对您有所帮助。
我对 dom-repeat
重绘的方式有疑问。下面的代码片段演示了过滤和排序简单的对象数组可能会向最终用户错误地呈现数据。
我确定这与 _applyFullRefresh
方法 (https://github.com/Polymer/polymer/blob/master/src/lib/template/dom-repeat.html#L482) 中的实例重用有关。
我能够修改此方法以通过重用具有匹配密钥的实例来创建有效的解决方案。可以在这里看到一个差异:https://github.com/Polymer/polymer/compare/master...TomK:patch-1
我的问题: dom-repeat
的补丁是否是我实现工作示例的唯一方法?
片段预期结果:
选择 filter/sort 的任意组合后,一行中的两个数字(item content
和 x-item content
)应始终相同。
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="basic polymer jsbin">
<meta charset="utf-8">
<base href="//polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id="x-item-test">
<template>
x-item content: [[_innerText]]
</template>
<script>
HTMLImports.whenReady(
function ()
{
Polymer(
{
is: 'x-item-test',
properties: {
_innerText: {type: String}
},
attached: function ()
{
Polymer.RenderStatus.afterNextRender(this, this.__updateProp.bind(this));
new MutationObserver(this.__updateProp.bind(this))
.observe(this, {childList: true, subtree: true, characterData: true});
},
__updateProp: function ()
{
var nodes = this.getEffectiveChildNodes(), output = '';
for(var i in nodes)
{
var n = nodes[i];
if(n.nodeType == 3 && n.nodeValue)
{
output += n.nodeValue;
}
}
this._innerText = output;
}
}
);
}
);
</script>
</dom-module>
<dom-module id="test-app">
<template>
<div>
Filter <input type="checkbox" checked="{{_applyFilter::change}}">
</div>
<div>
Sort <input type="checkbox" checked="{{_reverse::change}}">
</div>
<template is="dom-repeat" items="[[actions]]" filter="{{_filter(_applyFilter)}}" sort="{{_sort(_reverse)}}">
<div>Item content: [[item.id]] -
<x-item-test>[[item.id]]
<div>ignored</div>
</x-item-test>
</div>
</template>
</template>
<script>
HTMLImports.whenReady(
function ()
{
Polymer(
{
is: 'test-app',
properties: {
actions: {
type: Array,
value: [{id: '1', primary: true}, {id: '2'}, {id: '3', primary: true}, {id: '4'}]
},
_applyFilter: {type: Boolean, value: false},
_reverse: {type: Boolean, value: false}
},
_filter: function (applyFilter)
{
return function (item)
{
return !applyFilter || item.primary;
}
},
_sort: function (reverse)
{
return function (a, b)
{
if(reverse)
{
return a.id < b.id
}
return a.id >= b.id;
}
}
}
);
}
);
</script>
</dom-module>
</head>
<body>
<test-app></test-app>
</body>
</html>
在 Polymer 1.x 中,由于 dom-repeat
重用实例的方式,我认为没有好的方法可以完成您想要做的事情。
执行 属性 绑定而不是将光 DOM 子级传递给 x-item-test
将是在 1.x 中执行此操作的最佳方法。
对每个数组项进行实例查找是 O(n^2) 我认为这对于一般情况来说是不可接受的。
如果出于某种原因你真的需要使用 light DOM children,我能想到的最后一个(相当可怕的)选项是有一个遍历模板实例的 dom-change 监听器并对它们调用一些更新方法。
我无法想象任何比 属性 绑定更可取的用例,但有时我不是很有想象力。
我在 2.0 预览版中没有看到这个问题:
http://jsbin.com/vuritog/2/edit?html,output
希望对您有所帮助。