自定义元素的使用:
有两种类型的自定义元素:
- 自定义内置元素(Customized built-in element)继承自标准的 HTML 元素,例如
HTMLImageElement或HTMLParagraphElement。它们的实现定义了标准元素的行为。 - 独立自定义元素(Autonomous custom element)继承自 HTML 元素基类
HTMLElement。你必须从头开始实现它们的行为。
使用示例:
// 为这个元素创建类
class MyCustomElement extends HTMLElement {
static observedAttributes = ["color", "size"];
constructor() {
// 必须首先调用 super 方法
super();
}
connectedCallback() {
console.log("自定义元素添加至页面。");
}
disconnectedCallback() {
console.log("自定义元素从页面中移除。");
}
adoptedCallback() {
console.log("自定义元素移动至新页面。");
}
attributeChangedCallback(name, oldValue, newValue) {
console.log(`属性 ${name} 已变更。`);
}
}
customElements.define("my-custom-element", MyCustomElement);
方法1、@import
<div>
<my-custom-element></my-custom-element>
</div>
<script>
class MyCustomElement extends HTMLElement {
//这是自定义元素的生命周期钩子:每当元素添加到文档中时调用;规范建议开发人员尽可能在此回调中实现自定义元素的设定,而不是在构造函数中实现。
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>
@import "./index.css"; // 核心代码
</style>
<div class="title">我的自定义元素</div>
`;
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
//index.css文件
.title {
color: green;
}
方法2、::part
//HTML: 自定义元素内部
<div class="my-custom-element" part="my-custom-element">
<div part="top">Top</div>
<div part="bottom">Bottom</div>
</div>
//标签使用
<my-custom-element></my-custom-element>
//CSS: 外部CSS覆盖元素内部样式,part标注唯一标识
my-custom-element::part(top) {
/* 样式作用于 `top` 部分 */
}
my-custom-element::part(bottom) {
/* 样式作用于 `bottom` 部分 */
}
方法3、var
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
my-custom-element {
--background: #1e88e5;
--color: white;
--padding: 2rem 4rem;
--font-size: 1.5rem;
}
</style>
</head>
<body>
<div>
<my-custom-element></my-custom-element>
</div>
<script>
class MyCustomElement extends HTMLElement {
//这是自定义元素的生命周期钩子:每当元素添加到文档中时调用;规范建议开发人员尽可能在此回调中实现自定义元素的设定,而不是在构造函数中实现。
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>
button {
background: var(--background);
color: var(--color);
padding: var(--padding);
font-size: var(--font-size);
border: 0;
}
</style>
<div>我的自定义元素</div>
<button>按钮</button>
`;
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
</body>
</html>
方法4、通过属性传入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<my-custom-element css=".name{color:red;}"></my-custom-element>
</div>
<script>
class MyCustomElement extends HTMLElement {
static get observedAttributes() {
return ["css"];
}
constructor() {
super();
}
get css() {
return this.getAttribute("css");
}
set css(value) {
if (value === null || value === false) {
this.removeAttribute("css");
} else {
this.setAttribute("css", value);
}
}
connectedCallback() {
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.innerHTML = `
<style>
:host{
display: flex;
}
${this.css} // 核心代码
</style>
<div class="name">我的自定义元素</div>
`;
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
</body>
</html>
方法5、自定义组件内部定义修改样式函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<my-custom-element></my-custom-element>
</div>
<script>
class MyCustomElement extends HTMLElement {
// 核心代码
reStyle(els, styles) {
const elements = Array.isArray(els) ? els : [els];
elements.forEach((element) => Object.assign(element.style, styles));
}
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>
.title {
background: green;
}
</style>
<div class="title">我的自定义元素</div>
`;
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
<script>
const myEle = document.querySelector("my-custom-element");
const title = myEle.shadowRoot.querySelector(".title");
myEle.reStyle(title, {
color: "red",
width: "200px",
});
</script>
</body>
</html>
方法6、通过 slot 外部设置样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.content{
color: red;
}
</style>
</head>
<body>
<div>
<my-custom-element>
<div slot="title" class="content">具体内容</div>
</my-custom-element>
</div>
<script>
class MyCustomElement extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<div>我的自定义元素</div>
<div>
<slot name="title"></slot>
</div>
`;
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
<script></script>
</body>
</html>
方法7、fetch获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<my-custom-element> </my-custom-element>
<script>
class MyCustomElement extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<div class="title">我的自定义元素</div>
`;
// 获取样式
fetch("./index.css")
.then((res) => res.text())
.then((data) => {
let node = document.createElement("style");
node.innerHTML = data;
this.shadowRoot.appendChild(node);
});
}
}
window.customElements.define("my-custom-element", MyCustomElement);
</script>
</body>
</html>
//index.css文件
div {
color: red;
}
.title {
color: green;
}
方法8、CSS module import
//使用浏览器原生的import语法,但是import的是CSS文件而不是JS文件。
//把CSS文件直接作为模块引入。
import styles from "index.css";
class WhatsUp extends HTMLElement {
constructor() {
shadow.adoptedStyleSheets = [styles];
}
}