javascript创建的模板元素不起作用

时间:2019-12-22 07:19:13

标签: javascript web-component

如果我手动将一个template节点写入HTML,则可以在我的自定义元素中使用它。如果我创建一个template节点并在尝试使用它时使用javascript将其附加到HTML,则它为空...

在下面的示例中,我将template-a设置为常规HTML方式,并使用javascript将template-b设置为相同形状。我定义了一个使用两个模板的非常简单的自定义元素。只有template-a是可见的。

const sandbox = document.getElementById('sandbox')

const slot = document.createElement('slot')
slot.setAttribute('name', 'b')
slot.append('slot content goes here')
const em = document.createElement('em')
em.append(slot, '?')
const createdTemplate = document.createElement('template')
createdTemplate.setAttribute('id', 'template-b')
createdTemplate.append(em)
sandbox.append(createdTemplate)

customElements.define('test-element', class extends HTMLElement {
  constructor () {
    super()
    this.attachShadow({ mode: 'open' }).append(
      ...['template-a','template-b']
      .map(id =>
        document.getElementById(id).content.cloneNode(true)
      )
    )
  }
})
<div id="sandbox">
  <template id="template-a">
    <strong><slot name="a">slot content goes here</slot>!</strong>
  </template>
  <test-element>
    <span slot="a">some a slot content</span>
    <span slot="b">some b slot content</span>
  </test-element>
</div>

2 个答案:

答案 0 :(得分:1)

关于代码的一些注释:

this.shadowRoot

this.shadow = this.attachShadow({ mode: 'open' })

可以成为

this.attachShadow({ mode: 'open' })

这免费创建/设置了this.shadowRoot

appendChild vs.append

请注意,.appendChild(el)包含一个元素

.append()带一个数组

唯一的区别是appendChild() 返回对插入元素的引用,
并且append()不返回任何内容

所以您可以写:

em.appendChild(slot)
em.appendChild(document.createTextNode('?'))

em.append(slot, document.createTextNode('?'))

如果阵列中有节点:

let myElements = [slot, document.createTextNode('?')];

您可以使用ES6扩展运算符:

em.append(...myElements)

这意味着您可以编写:

this.shadow.appendChild(document.getElementById('template-a').content.cloneNode(true))
this.shadow.appendChild(document.getElementById('template-b').content.cloneNode(true))

为:

this.shadowRoot
 .append(
   ...['a','b']
      .map(templ => document.getElementById(`template-${templ}`).content.cloneNode(true))
  )

答案 1 :(得分:0)

template节点具有一个特殊的content属性,该属性保存其子级。 (我有点知道,但认为它比它更具魔力)。如果这行:

createdTemplate.append(em)

更改为

createdTemplate.content.append(em)

然后一切正常

const sandbox = document.getElementById('sandbox')

const slot = document.createElement('slot')
slot.setAttribute('name', 'b')
slot.append('slot content goes here')
const em = document.createElement('em')
em.append(slot, '?')
const createdTemplate = document.createElement('template')
createdTemplate.setAttribute('id', 'template-b')
createdTemplate.content.append(em)
sandbox.append(createdTemplate)

customElements.define('test-element', class extends HTMLElement {
  constructor () {
    super()
    this.attachShadow({ mode: 'open' }).append(
      ...['template-a','template-b']
      .map(id =>
        document.getElementById(id).content.cloneNode(true)
      )
    )
  }
})
<div id="sandbox">
  <template id="template-a">
    <strong><slot name="a">slot content goes here</slot>!</strong>
  </template>
  <test-element>
    <span slot="a">some a slot content</span>
    <span slot="b">some b slot content</span>
  </test-element>
</div>