在我的组件中,我想重复一个项目列表,其中包含由组件的光dom提供的模板.例如:
<template is="dom-repeat" items="{{items}}">
<content select="#itemTemplate"></content>
</template>
但是,似乎Polymer只插入轻量级元素#itemTemplate一次而不是多次.有没有其他方法来重复轻dom元素?
最佳答案 我创建了一个简单的原型,它允许您指定轻型DOM模板的重复次数.
因为内容在轻量级DOM中,所以您可以像往常一样从外部设置样式.并且模板内部的数据绑定也有效,因为我已经从Templatizer实现了_forwardParentProp和_forwardParentPath方法.
请注意,我没有实现特定于实例的属性,这将允许每行特定的变量,例如index和item.当然,这可以完成,但需要更多的工作.
查看原型:JSBin.
好的,我们来详细说明:
test元素的使用以及对两个输入元素的数据绑定非常简单:
<template is="dom-bind">
Number of repeats: <input type="text" value="{{repeats::input}}" /> <br />
Custom message: <input type="text" value="{{customMessage::input}}" />
<test-element repeats="{{repeats}}">
<template>
<h1>Title!</h1>
<p>
Custom message: <em>[[customMessage]]</em>
</p>
</template>
</test-element>
</template>
注意dom-bind,它是创建数据绑定范围所必需的.
至于test-element,整个源代码如下所示:
<dom-module id="test-element">
<template>
<style>
:host {
display: block;
}
</style>
<content></content>
</template>
<script>
Polymer({
is: 'test-element',
behaviors: [
Polymer.Templatizer,
],
properties: {
repeats: {
type: Number,
value: 3,
notify: true,
},
},
observers: [
'_repeatsChanged(repeats)',
],
_repeatsChanged: function(repeats) {
// First time only: initialize template
if (this.template === undefined) {
this.template = Polymer.dom(this).querySelector('template');
this.templatize(this.template);
}
// Remove previously stamped children
while (Polymer.dom(this).firstChild) {
Polymer.dom(this).removeChild(Polymer.dom(this).firstChild);
}
// Stamp new ones
this.stamped = new Array(repeats);
var inst;
for (var i = 0; i < repeats; i++) {
inst = this.stamp(null);
this.stamped[i] = inst.root.querySelector('*');
Polymer.dom(this).appendChild(inst.root);
}
},
// Copied from iron-list
_forwardParentProp: function(prop, value) {
if (this.stamped) {
this.stamped.forEach(function(item) {
item._templateInstance[prop] = value;
}, this);
}
},
// Copied from iron-list
_forwardParentPath: function(path, value) {
if (this.stamped) {
this.stamped.forEach(function(item) {
item._templateInstance.notifyPath(path, value, true);
}, this);
}
},
});
</script>
</dom-module>
只有一个属性,重复,指定标记实例的数量.默认值为3.为了适应所述属性值的更改,已创建观察者.这也是冲压发生的地方:
_repeatsChanged: function(repeats) {
// First time only: initialize template
if (this.template === undefined) {
this.template = Polymer.dom(this).querySelector('template');
this.templatize(this.template);
}
// Remove previously stamped children
while (Polymer.dom(this).firstChild) {
Polymer.dom(this).removeChild(Polymer.dom(this).firstChild);
}
// Stamp new ones
this.stamped = new Array(repeats);
var inst;
for (var i = 0; i < repeats; i++) {
inst = this.stamp(null);
this.stamped[i] = inst.root.querySelector('*');
Polymer.dom(this).appendChild(inst.root);
}
},
>首先(并且只有一次),从轻量级DOM读取模板
调用模板化方法.这个方法初始化了
模板化行为.
>其次,所有以前盖章的孩子都被移除(这样的话
元素不仅无限积累).
>第三,根据目前的价值,新生儿被加盖印章
重复.所有标记的实例都保存到this.stamped中
从外部到工作的数据绑定需要.
最后但并非最不重要的是,Templatizer行为是通过两种方法实现的(两种方法未实现):
// Copied from iron-list
_forwardParentProp: function(prop, value) {
if (this.stamped) {
this.stamped.forEach(function(item) {
item._templateInstance[prop] = value;
}, this);
}
},
// Copied from iron-list
_forwardParentPath: function(path, value) {
if (this.stamped) {
this.stamped.forEach(function(item) {
item._templateInstance.notifyPath(path, value, true);
}, this);
}
},
这两种方法都取自铁清单.他们遍历标记的子项并传播属性更改和路径通知.