Polymer中如何利用dom-repeat循环渲染数组指定的自定义元素?
Great question! Unfortunately, the syntax you tried (<[[item]]></[[item]]>) won't work directly because Polymer's template parser doesn't dynamically replace tag names like that. But there are a couple of solid ways to achieve what you're aiming for:
1. 针对扩展内置元素的自定义元素(使用is属性)
If your custom elements extend native HTML elements (like div or span), you can use the is attribute to bind the dynamic tag name. This works because it's part of the custom elements spec for built-in extensions.
First, define your custom element like this (extending a native element):
class MyElement1 extends HTMLDivElement { constructor() { super(); this.textContent = "I'm my-element1!"; } } customElements.define('my-element1', MyElement1, { extends: 'div' });
Then in your Polymer template, use dom-repeat with the is attribute:
<template is="dom-repeat" items="[[blocks]]"> <div is="[[item]]"></div> </template>
2. 针对独立自定义元素(结合模板与JavaScript)
For custom elements that don't extend native elements (the more common case), you'll need to pair dom-repeat with a bit of JavaScript to dynamically create and insert the elements. This is the most reliable approach for standard custom elements.
Here's a complete example:
<dom-module id="element-wrapper"> <template> <!-- Use dom-repeat to create containers for each dynamic element --> <template is="dom-repeat" items="[[blocks]]" id="blocksRepeat"> <div class="element-container"></div> </template> </template> <script> class ElementWrapper extends Polymer.Element { static get is() { return 'element-wrapper'; } static get properties() { return { blocks: { type: Array, value: () => ['my-element1', 'my-element2', 'my-element3'] } }; } connectedCallback() { super.connectedCallback(); // Wait for dom-repeat to render containers before adding elements this.$.blocksRepeat.addEventListener('dom-change', this._renderDynamicElements.bind(this)); } _renderDynamicElements() { const containers = this.shadowRoot.querySelectorAll('.element-container'); containers.forEach((container, index) => { const tagName = this.blocks[index]; // Ensure the custom element is registered before creating it if (customElements.get(tagName)) { const element = document.createElement(tagName); container.appendChild(element); } else { console.warn(`Custom element "${tagName}" is not registered yet!`); } }); } // Add an observer if your blocks array might change dynamically static get observers() { return ['_onBlocksChange(blocks.splices)']; } _onBlocksChange() { // Clear existing elements first const containers = this.shadowRoot.querySelectorAll('.element-container'); containers.forEach(container => container.innerHTML = ''); // Re-render the updated elements this._renderDynamicElements(); } } customElements.define(ElementWrapper.is, ElementWrapper); </script> </dom-module>
Key Notes:
- Always make sure your custom elements are registered (via
customElements.define()) before trying to create them dynamically. If elements load asynchronously, you might need to usecustomElements.whenDefined(tagName)to wait for them. - The
dom-changeevent ensures we only try to add elements after thedom-repeathas finished rendering its containers. - The observer for
blocks.spliceshandles cases where your array is updated (items added/removed) by re-rendering the elements.
内容的提问来源于stack exchange,提问作者Andrew Noblet

