HTML 自定义元素子容器
HTML Custom Element Child Container
我正在尝试制作经典的菜单栏,同时尝试使用 Web 组件。我从来没有和他们一起玩过,这是我第一次涉足这个主题。它们似乎是一个非常强大的工具,但似乎没有太多关于我正在尝试做什么的信息。
我有一个自定义 html 元素树,目前看起来像这样(在调用构造函数之后):
<menu-bar>
<sub-menu label="some label">
<label>some label</label>
<menu-item></menu-item>
<menu-item></menu-item>
<menu-item></menu-item>
</sub-menu>
</menu-bar>
如何让自定义元素将其变成...
<menu-bar>
<sub-menu label="some label">
<label>some label</label>
<div>
<menu-item></menu-item>
<menu-item></menu-item>
<menu-item></menu-item>
</div>
</sub-menu>
</menu-bar>
...何时调用子菜单的构造函数?也可以使 div 成为阴影 dom 的一部分而菜单项元素不在阴影中 dom?
相关示例代码
class MenuBar extends HTMLElement {
constructor() {
super();
}
};
class SubMenu extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "open"});
this.labelElement = document.createElement("label");
shadowRoot.appendChild(this.labelElement);
}
static get observedAttributes() {
return ["label"];
}
attributeChangedCallback(pName, pOldValue, pNewValue) {
switch (pName) {
case "label":
this.labelElement.innerHTML = pNewValue;
break;
}
}
};
class MenuItem extends HTMLElement {
constructor() {
super();
}
};
window.customElements.define("menu-bar", MenuBar);
window.customElements.define("sub-menu", SubMenu);
window.customElements.define("menu-item", MenuItem);
非常感谢任何帮助,因为我只是在学习它们是如何工作的,并且正在寻找更多关于如何使用 Web 组件操作预定义 html 的详细信息,而不仅仅是直接回答这个问题例子本身。
您需要使用 <slot>
让非 shadowDOM 子元素显示在元素的 shadowDOM 中。
示例:
class MenuBar extends HTMLElement {
constructor() {
super();
}
};
class SubMenu extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "open"});
this.labelElement = document.createElement("label");
let temp = document.createElement("div");
temp.innerHTML = '<slot></slot>';
shadowRoot.appendChild(this.labelElement);
shadowRoot.appendChild(temp);
}
static get observedAttributes() {
return ["label"];
}
attributeChangedCallback(pName, pOldValue, pNewValue) {
switch (pName) {
case "label":
this.labelElement.innerHTML = pNewValue;
break;
}
}
};
class MenuItem extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"}).innerHTML = `
<style>
:host {
background-color: #eee;
border: 1px solid #ddd;
display:block;
margin: 1px 0;
}
</style>
<slot></slot>
`;
}
};
window.customElements.define("menu-bar", MenuBar);
window.customElements.define("sub-menu", SubMenu);
window.customElements.define("menu-item", MenuItem);
<menu-bar>
<sub-menu label="some label">
<menu-item>1</menu-item>
<menu-item>2</menu-item>
<menu-item>3</menu-item>
</sub-menu>
</menu-bar>
在您的 SubMenu
中,我添加了带有 <slot>
的 <div>
来容纳所有 <menu-item>
组件。
我还添加了一些小的 CSS 以便更容易看到子元素。
我正在尝试制作经典的菜单栏,同时尝试使用 Web 组件。我从来没有和他们一起玩过,这是我第一次涉足这个主题。它们似乎是一个非常强大的工具,但似乎没有太多关于我正在尝试做什么的信息。
我有一个自定义 html 元素树,目前看起来像这样(在调用构造函数之后):
<menu-bar>
<sub-menu label="some label">
<label>some label</label>
<menu-item></menu-item>
<menu-item></menu-item>
<menu-item></menu-item>
</sub-menu>
</menu-bar>
如何让自定义元素将其变成...
<menu-bar>
<sub-menu label="some label">
<label>some label</label>
<div>
<menu-item></menu-item>
<menu-item></menu-item>
<menu-item></menu-item>
</div>
</sub-menu>
</menu-bar>
...何时调用子菜单的构造函数?也可以使 div 成为阴影 dom 的一部分而菜单项元素不在阴影中 dom?
相关示例代码
class MenuBar extends HTMLElement {
constructor() {
super();
}
};
class SubMenu extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "open"});
this.labelElement = document.createElement("label");
shadowRoot.appendChild(this.labelElement);
}
static get observedAttributes() {
return ["label"];
}
attributeChangedCallback(pName, pOldValue, pNewValue) {
switch (pName) {
case "label":
this.labelElement.innerHTML = pNewValue;
break;
}
}
};
class MenuItem extends HTMLElement {
constructor() {
super();
}
};
window.customElements.define("menu-bar", MenuBar);
window.customElements.define("sub-menu", SubMenu);
window.customElements.define("menu-item", MenuItem);
非常感谢任何帮助,因为我只是在学习它们是如何工作的,并且正在寻找更多关于如何使用 Web 组件操作预定义 html 的详细信息,而不仅仅是直接回答这个问题例子本身。
您需要使用 <slot>
让非 shadowDOM 子元素显示在元素的 shadowDOM 中。
示例:
class MenuBar extends HTMLElement {
constructor() {
super();
}
};
class SubMenu extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "open"});
this.labelElement = document.createElement("label");
let temp = document.createElement("div");
temp.innerHTML = '<slot></slot>';
shadowRoot.appendChild(this.labelElement);
shadowRoot.appendChild(temp);
}
static get observedAttributes() {
return ["label"];
}
attributeChangedCallback(pName, pOldValue, pNewValue) {
switch (pName) {
case "label":
this.labelElement.innerHTML = pNewValue;
break;
}
}
};
class MenuItem extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"}).innerHTML = `
<style>
:host {
background-color: #eee;
border: 1px solid #ddd;
display:block;
margin: 1px 0;
}
</style>
<slot></slot>
`;
}
};
window.customElements.define("menu-bar", MenuBar);
window.customElements.define("sub-menu", SubMenu);
window.customElements.define("menu-item", MenuItem);
<menu-bar>
<sub-menu label="some label">
<menu-item>1</menu-item>
<menu-item>2</menu-item>
<menu-item>3</menu-item>
</sub-menu>
</menu-bar>
在您的 SubMenu
中,我添加了带有 <slot>
的 <div>
来容纳所有 <menu-item>
组件。
我还添加了一些小的 CSS 以便更容易看到子元素。