【发布时间】:2021-05-11 21:04:44
【问题描述】:
我正在尝试创建一个自定义 HTML 组件,该组件为其拥有的每个子元素创建选项卡。这是该自定义组件的代码:
const code_window = document.getElementById("window");
class CodeWindow extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
});
this.shadowRoot.appendChild(code_window.content.cloneNode(true));
this.code = this.shadowRoot.getElementById("code");
this.tabbar = this.shadowRoot.getElementById("tabbar");
this.code.addEventListener("slotchange", e => {
var elems = e.target.assignedNodes();
for (let i = 0; i < elems.length; i++) {
var tab = document.createElement("div");
tab.classList.add("tab");
var name = elems[i].getAttribute("name");
tab.innerHTML = name;
tab.setAttribute("name", name);
this.tabbar.appendChild(tab);
if (elems[i].hasAttribute("active")) this.activateTab(name);
tab.addEventListener("click", e => this.activateTab(e.target.getAttribute("name")));
}
if (!this.previous_tab && this.tabbar.children.length > 0) this.activateTab(this.tabbar.children[0].getAttribute("name"));
});
}
activateTab(name) {
if (this.previous_tab) {
this.previous_frame.removeAttribute("active");
this.previous_tab.removeAttribute("active");
}
var tabs = this.tabbar.children,
frames = this.code.assignedElements();
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].getAttribute("name") == name) {
tabs[i].setAttribute("active", "");
frames[i].setAttribute("active", "");
this.previous_frame = frames[i];
this.previous_tab = tabs[i];
break;
}
}
}
}
customElements.define("c-window", CodeWindow);
<template id="window">
<style>
:host {
display: flex;
flex-direction: column;
}
#titlebar {
display: flex;
background-color: green;
}
#tabbar {
flex-grow: 1;
display: flex;
}
#tabbar .tab {
display: flex;
align-items: center;
padding: 5px 10px;
background-color: #bbb;
}
#tabbar .tab[active] {
background-color: #fff;
}
#code {
flex-grow: 1;
display: block;
position: relative;
}
#code::slotted(*) {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 5px;
display: none;
}
#code::slotted(*[active]) {
display: block;
}
</style>
<div id="titlebar">
<div id="tabbar"></div>
</div>
<slot id="code" name="frames"></slot>
</template>
<c-window style="border: 2px solid green; height: 300px;">
<div slot="frames" name="Content 1">Contents of tab 1</div>
<div slot="frames" name="Content 2">Contents of tab 2</div>
</c-window>
自定义组件内部有一个插槽,我希望每次添加子元素时都应添加一个选项卡,如果删除了子元素,则应删除与该子元素关联的选项卡。
但slotchange 事件不包含有关已添加/删除哪个元素的信息,因此目前,每次调用slotchange 事件时,我都必须循环遍历slot.assignedElements() 并为每个元素创建选项卡。这意味着对于特定的孩子,将创建重复的选项卡,这也可能是 CPU 密集型的。
所以,我在想是否有某种方法可以获取有关已修改元素的信息,以便仅对已修改元素执行操作。有没有办法只获得修改后的元素?如果没有,我可以申请什么方法来实现这一点?
【问题讨论】:
-
请访问help center,使用tour查看内容和How to Ask。做一些研究,搜索关于SO的相关主题;如果您遇到困难,请发布您尝试的minimal reproducible example,注意输入和预期输出,最好在Stacksnippet
-
不行,你要根据
assignedNodes自己记账;它就像在您处理的节点上设置属性一样简单。您的(提升)var而不是letusage 占用更多 CPU 周期。
标签: javascript html custom-component