javascript 创建的模板元素不起作用
javascript created template element not working
如果我手动将 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>
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>
关于您的代码的一些注释:
this.shadowRoot
this.shadow = this.attachShadow({ mode: 'open' })
可以变成
this.attachShadow({ mode: 'open' })
这个creates/setsthis.shadowRoot
免费
appendChild 与 append
注意 .appendChild(el)
取一个元素
和.append()
接受一个数组
唯一的区别是appendChild()
returns对插入元素的引用,
append()
returns 什么都没有
所以你可以这样写:
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))
)
如果我手动将 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>
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>
关于您的代码的一些注释:
this.shadowRoot
this.shadow = this.attachShadow({ mode: 'open' })
可以变成
this.attachShadow({ mode: 'open' })
这个creates/setsthis.shadowRoot
免费
appendChild 与 append
注意 .appendChild(el)
取一个元素
和.append()
接受一个数组
唯一的区别是appendChild()
returns对插入元素的引用,
append()
returns 什么都没有
所以你可以这样写:
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))
)