影子 dom 内的重复命名插槽不起作用
duplicated named slot inside shadow dom not working
我有一个看起来像这样的自定义元素:
class RepeatMe extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
let slot = document.createElement('slot');
slot.setAttribute('name', 'bar');
this.shadowRoot.append(slot);
slot = document.createElement('slot');
slot.setAttribute('name', 'content');
this.shadowRoot.append(slot);
slot = document.createElement('slot');
slot.setAttribute('name', 'bar');
this.shadowRoot.append(slot);
}
}
window.customElements.define('repeat-me', RepeatMe);
我的使用方式如下:
<repeat-me>
<div slot="bar">I'm a bar</div>
<div slot="content">I'm some content</div>
</repeat-me>
我想在阴影dom中重复插槽bar
(因为内容在开头和结尾是相同的),但我得到的是只有第一个插槽被渲染,第二个是空的。我想用 shadow dom 插槽做的事情是可能的,还是你知道一些方法来实现这样的事情?
不,插槽是唯一的,
并且多个 lightDOM 元素可以插入到同一个 SLOT
将 SLOT 视为您的邮箱;你想让你的邮件总是复制到另一个邮箱吗?
如果您有此要求,则需要一个过滤器来复制电子邮件(或插槽内容)
对于 WebComponents,有 2 个选项可以复制:
将 <span slot="bar">
克隆到 shadowRoot
内的其他(非插槽)DOM 元素
克隆到新的 lightDOM 元素 <span slot="duplicate_bar1">
用于新插入的内容
下面的代码有两个选项 slotchange
发生在 <span slot="bar">
的事件(插槽中的新内容)
在 slotchange
插槽内容被克隆到 class="duplicate_bar"
(let dups = ...
)
在 slotchange
上创建了新的灯 DOM 元素 (let dupslots = ...
)
请注意,只有方法 2. 使用 <slot>
功能,您可以使用 :slotted
样式
此代码仅复制内容;它不会清理删除的 SLOT 内容。
<my-element>
<span slot="bar"> ONE </span>
<span slot="bar"> TWO </span>
<span slot="content"> content </span>
</my-element>
<template id="MY-ELEMENT">
<style>
::slotted(*) { background: lightgreen }
</style>
slot bar: <slot name="bar"></slot>
<br> slot: content: <slot name="content"></slot>
<br>Duplicate in SPAN: <span class="duplicate_bar"></span>
<br>Duplicate in B:<b class="duplicate_bar"></b>
<br>duplicate_bar1:<slot name="duplicate_bar1"></slot>
<br>duplicate_bar2:<slot name="duplicate_bar2"></slot>
</template>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
let template = id => document.getElementById(id).content.cloneNode(true);
super().attachShadow({mode: 'open'}).append(template(this.nodeName));
let slotname = "bar";
let slot = this.shadowRoot.querySelector(`[name="${slotname}"]`);
slot.addEventListener("slotchange", (evt) => {
let assigned = slot.assignedNodes();
let dups = [...this.shadowRoot.querySelectorAll(".duplicate_" + slotname)];
let dupslots = [...this.shadowRoot.querySelectorAll(`slot[name*="duplicate_bar"]`)];
assigned.forEach(node => {
dups.forEach(el => el.append(node.cloneNode(true)));
dupslots.forEach(duplicateslot => {
let newNode = node.cloneNode(true);
newNode.slot = duplicateslot.name; // set BEFORE adding to DOM! otherwise 'bar' slotchange Events triggers on it
this.append(newNode);
})
});
});
}
});
</script>
我有一个看起来像这样的自定义元素:
class RepeatMe extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
let slot = document.createElement('slot');
slot.setAttribute('name', 'bar');
this.shadowRoot.append(slot);
slot = document.createElement('slot');
slot.setAttribute('name', 'content');
this.shadowRoot.append(slot);
slot = document.createElement('slot');
slot.setAttribute('name', 'bar');
this.shadowRoot.append(slot);
}
}
window.customElements.define('repeat-me', RepeatMe);
我的使用方式如下:
<repeat-me>
<div slot="bar">I'm a bar</div>
<div slot="content">I'm some content</div>
</repeat-me>
我想在阴影dom中重复插槽bar
(因为内容在开头和结尾是相同的),但我得到的是只有第一个插槽被渲染,第二个是空的。我想用 shadow dom 插槽做的事情是可能的,还是你知道一些方法来实现这样的事情?
不,插槽是唯一的,
并且多个 lightDOM 元素可以插入到同一个 SLOT
将 SLOT 视为您的邮箱;你想让你的邮件总是复制到另一个邮箱吗?
如果您有此要求,则需要一个过滤器来复制电子邮件(或插槽内容)
对于 WebComponents,有 2 个选项可以复制:
将
内的其他(非插槽)DOM 元素<span slot="bar">
克隆到 shadowRoot克隆到新的 lightDOM 元素
<span slot="duplicate_bar1">
用于新插入的内容
下面的代码有两个选项 slotchange
发生在 <span slot="bar">
的事件(插槽中的新内容)
在
slotchange
插槽内容被克隆到class="duplicate_bar"
(let dups = ...
)在
slotchange
上创建了新的灯 DOM 元素 (let dupslots = ...
)
请注意,只有方法 2. 使用 <slot>
功能,您可以使用 :slotted
样式
此代码仅复制内容;它不会清理删除的 SLOT 内容。
<my-element>
<span slot="bar"> ONE </span>
<span slot="bar"> TWO </span>
<span slot="content"> content </span>
</my-element>
<template id="MY-ELEMENT">
<style>
::slotted(*) { background: lightgreen }
</style>
slot bar: <slot name="bar"></slot>
<br> slot: content: <slot name="content"></slot>
<br>Duplicate in SPAN: <span class="duplicate_bar"></span>
<br>Duplicate in B:<b class="duplicate_bar"></b>
<br>duplicate_bar1:<slot name="duplicate_bar1"></slot>
<br>duplicate_bar2:<slot name="duplicate_bar2"></slot>
</template>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
let template = id => document.getElementById(id).content.cloneNode(true);
super().attachShadow({mode: 'open'}).append(template(this.nodeName));
let slotname = "bar";
let slot = this.shadowRoot.querySelector(`[name="${slotname}"]`);
slot.addEventListener("slotchange", (evt) => {
let assigned = slot.assignedNodes();
let dups = [...this.shadowRoot.querySelectorAll(".duplicate_" + slotname)];
let dupslots = [...this.shadowRoot.querySelectorAll(`slot[name*="duplicate_bar"]`)];
assigned.forEach(node => {
dups.forEach(el => el.append(node.cloneNode(true)));
dupslots.forEach(duplicateslot => {
let newNode = node.cloneNode(true);
newNode.slot = duplicateslot.name; // set BEFORE adding to DOM! otherwise 'bar' slotchange Events triggers on it
this.append(newNode);
})
});
});
}
});
</script>