原生组件化开发方案。Web Component是一套允许你创建可重用的定制元素的技术,它允许我们创建一个包含html结构、js脚本和css样式的可复用组件。
组成(三项主要技术)
- Custom Elements:一组 JavaScript API,允许开发者定义自己的 HTML 元素和其行为。
- Shadow DOM:一组 JavaScriptAP!,提供了一种将 HTML结构、样式和行为封装在一个独立的、可隔离的作用域内的机制。
- HTML Templates: 允许开发者定义 HTML 结构的模板,可以作为自定义元素结构的基础被多次重用。
生命周期
connectedCallback: 当自定义元素第一次被连接到文档DOM时被调用。
disconnectedCallback: 当自定义元素与文档DOM断开连接时被调用。
adoptedCallback: 当自定义元素被移动到新文档时被调用。
attributeChangedCallback: 当自定义元素的一个属性被增加、移除或更改时被调用。
基本方法
- 创建一个类或函数来指定web组件的功能,如果使用类的方式编写Web Component,需要使用 ECMAScript 2015 的类语法。
- 使用 CustomElementRegistry.define() 方法注册新的自定义元素 ,并向其传递要定义的元素名称、指定元素功能的类、以及可选的其所继承自的元素。
- 如果需要的话,使用 Element.attachShadow() 方法将一个 shadow DOM 附加到自定义元素上。使用通常的 DOM 方法向 shadow DOM 中添加子元素、事件监听器等等。
- 如果需要的话,使用 和 定义一个 HTML 模板。再次使用常规 DOM 方法克隆模板并将其附加到你的 shadow DOM 中。
- 在页面任何你喜欢的位置使用自定义元素,就像使用常规 HTML 元素那样。
<template>
包含一个 HTML 片段,不会在文档初始化时渲染。但是可以在运行时使用 JavaScript 显示。主要用作自定义元素结构的基础
<slot>
web 组件内部的占位符,你可以使用自己的标记来填充该占位符
customElements.define(
// 元素名,必须是Kebab case命名
// 目的是在页面中以<github-icon />去引用
"my-btn",
// 定义类,需要继承自HTMLElement
class extends HTMLElement {
// 构造器
constructor() {
// 必须调用父级构造
super();
// 获取上一步定义的template模板
// const template = document.getElementById("test");
// 获取模板内容
// const templateContent = template.content;
// 获取本元素的影子DOM树根,mode为true表示以后可以通过JavaScript直接外部访问根节点
// const shadowRoot = this.attachShadow({ mode: "open" });
// 将template的内容克隆并附加到shadowRoot,
// shadowRoot.appendChild(
// true表示深拷贝
// templateContent.cloneNode(true)
// );
let btn = document.createElement("button");
btn.innerHTML = `888888`;
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(
btn
);
}
}
)
class MyButton extends HTMLElement {
constructor() {
super();
let value = this.getAttribute("value");
// 可以直接放入到innerHTML中
// this.innerHTML = `<button>custom-button ${value}</button>`
// 也可以通过appendChild的方式添加元素对象
let btn = document.createElement("button");
btn.innerHTML = `custom-button ${value}`;
btn.addEventListener('click', () => {
this.setAttribute("name", "testtest");
this.setAttribute("value", 9999);
})
this.appendChild(btn);
}
// 当 custom element首次被插入文档DOM时,被调用
connectedCallback() {
console.log("connectedCallback");
}
// 当 custom element从文档DOM中删除时,被调用
disconnectedCallback() {
console.log("disconnectedCallback");
}
// 当 custom element增加、删除、修改自身属性时,被调用
attributeChangedCallback(name, oldValue, newValue) {
console.log("attribute", name, oldValue, newValue);
}
// 声明需要监听的属性名,只有这些属性变化时才会触发attributeChangedCallback
static get observedAttributes() {
return ["name", "url", "value"];
}
}
//参数一:自定义元素名,格式有要求:短线连接的字符串
//参数二:自定义元素构造器
//参数三:可选,含有 extends 属性的对象。指定所创建的元素继承自哪个内置元素,可以继承任何内置元素
window.customElements.define("my-button", MyButton );
<template id="form-template">
<style>
button{ background: #fff}
</style>
<slot name="title"></slot>
<input type="text">
<button>新增</button>
</template>
<form-template
name="form-template"
value="90"
>
<div slot="title">姓名</div>
</form-template>