我有一个dom-repeat模板(Polymer 1.2.3),并希望它根据模型渲染元素。
根据item
中的值,模板应呈现按钮或复选框或事先未知的其他内容。这就是我试过的:
<template is="dom-repeat" items=[[myItems]]>
<div>[[_render(item)]]</div>
</template>
_render
函数在这里返回一个DOM元素,但这不起作用(如预期的那样)。
_render: function() {
return document.createElement('paper-button');
}
如果在_render
函数的调用中模板将添加对它将要添加的DOM元素的引用,那么对于这种事情有什么用处。然后我可以用它来按需添加孩子。
答案 0 :(得分:0)
我也尝试过并且似乎无论如何都不能将元素作为要在dom-repeat中呈现的项目传递。 根据您的问题的复杂性和您想要呈现的内容,我只能想到两个解决方案。
1)这里充斥着dom-if元素,看起来很乱
<script>
Polymer({
is: 'your-element',
properties: {
myItems: {
type: Array,
value: [
{ type: 'checkbox', other: 'something', },
{ type: 'button', other: 'something else', },
]
},
},
isCheckbox: item => item.type === 'checkbox',
isButton: item => item.type === 'button',
});
</script>
<template is="dom-repeat" items="[[myItems]]">
<div>
<template id="dom-if" if="{{isCheckbox(item)}}">
<input type="checkbox" other="{{item.other}}" />
</template>
<template id="dom-if" if="{{isButton(item)}}"">
<paper-button other="{{item.other}}" ></paper-button>
</template>
</div>
</template>
2)这会在你的外部和内部dom之间留下恼人的自定义重复元素,并且会使访问渲染元素变得更加困难
<dom-module id="custom-repeat">
<template>
</template>
</dom-module>
<custom-repeat array="{{anArrayOfElementProperties}}"></custom-repeat>
<script>
HTMLImports.whenReady(function () {
Polymer({
is: 'custom-repeat',
properties: {
items: {
type: Array,
// a default value just for an example
value: [
{name: 'paper-fab', icon: 'add' },
{name: 'iron-icon', icon: 'star' },
{name: 'paper-fab', icon: 'alarm' },
{name: 'iron-icon', icon: 'apps' },
],
observer: 'itemsChanged',
},
},
itemsChanged: function(items) {
// Delete all children
// Add new children based on items
},
});
});
</script>
示例2显示为here
我真的不喜欢任何一个答案,但希望它可以让你度过难关,直到有人找到一种方法来改变dom-repeat元素呈现允许在实际节点中传递的方式,或理解何时传递引用DOM节点。
答案 1 :(得分:0)
我尝试使用记录在案here的Polymer DOM-API挂钩dom-repeat模板的渲染操作。使用这种方法你只需要做这样的事情。
Polymer.dom(this.$.domrep).observeNodes(function(info) {
var nList = info.addedNodes.filter(function(node) {
return (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'DIV')
});
this.processNewNodes(nList);
})
在processNewNodes
函数中,您可以将元素附加到dom-repeat模板呈现的节点。然而,由于不同原因,这不是一个好的解决方案。例如它不能与iron-list
中使用的模板一起使用。可能会发生添加节点但节点的模型尚未在模板实例中可用的情况。这意味着您无法根据模型将子节点附加到列表项。
这是我最终使用的解决方案,我很满意:
我为列表项创建了第二个dom-module,我将其用作dom-repeat
或iron-list
元素中的节点。您可以将DOM元素作为属性传递给此list-item元素。
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="list-item">
<template></template>
</dom-module>
<script>
Polymer({
is: 'list-item',
properties: {
renderObject: {
type: Object,
observer: '_render'
}
},
_render: function(newV) {
if (!newV) return true;
var root = Polymer.dom(this.root);
// remove previously rendered nodes
while (root.firstChild) {
root.removeChild(root.firstChild)
}
root.appendChild(newV);
}
});
</script>
每当您更改模型时,list-item都将丢弃并重新创建渲染节点。如果您不希望删除并重新创建每个模型更改上的项目,那么您应该能够将第二个属性itemValue
添加到列表项目中。然后,您可以观察itemValue
中的更改,并根据需要调整现有DOM元素。
这种方法将模板化器的动作与模板项的渲染动作分开。因此不会产生任何干扰。