<-Home
Web Component
Web Component 是一套封装 自定义 可重用 HTML 定制元素的技术;其核心技术主要包括:
- Custom Elements
- Shadow DOM
- Template && Slot
基本定义方式
- CustomElementsRegistry.define(name, Clazz, options)
- Clazz 可以有两种方式
- 自主定制元素:必须继承 HTMLElement 类, 使用方式为
- 自定义内置元素:可以继承 HTMLDIVElement、HTMLHTMLParagraphElement 等,使用方式为 <div is='defined-name'></div>
- 自主定制元素:必须继承 HTMLElement 类, 使用方式为
- 以上两种方式都可以使用 template && slot
- 最终需要 通过attachShadow 返回的shadow 和document 进行conenct
关于自定义元素的name 参数
- 需要满足特定规则
- 特定规则参考 html.spec.whatwg.org
CustomElementsRegistry 实例方法
- define(name: 自定义元素名称, constructor:自定义元素构造器,options:{ extends: 指定继承已创建好的元素}): void
- get: (name: 已经通过define 自定义的元素的名称): 返回对应的的构造器,如果未曾定义则返回undefined
- upgrade:(rootNode:已经通过document.createElement 定义的节点): void; 在该节点通过define定义前后皆可通过upgrade 进行升级
- whenDefine(name): Promise
; 如果name 不满足规则, 会reject 一个 SyntaxError - 以上方法都不能通过构造实例使用,会提示Illegal Error,在全局对象customElements 中可以直接使用;
<!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>
<button id="upgrade">upgrade</button>
<licheng-hello id="hello">hello world!!!</licheng-hello>
<script src="./main.js"></script>
</body>
</html>
const btn = document.getElementById('upgrade');
const helloEl = document.getElementById('hello');
class Hello extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = `
.hello {
color: orange;
background-color: grey;
padding: 5px 15px;
border-radius: 4px;
display: inline-block;
width: 200px;
text-align: center;
}
`;
const div = document.createElement('div');
div.classList.add('hello');
div.innerHTML = '<span>(hello licheng ^_^)</span>';
shadow.appendChild(style);
shadow.appendChild(div);
}
}
// whenDefine
customElements.whenDefined('licheng-hello').then(res => {
console.log('when define licheng-hello', res);
// upgrade
customElements.upgrade(helloEl);
}).catch(reason=> {
console.error(reason);
});
btn.onclick = e => {
// get
const definedHello = customElements.get('licheng-hello');
if (typeof definedHello === 'function') return;
// define
customElements.define('licheng-hello', Hello);
}
Web Component 生命周期
- connectedCallback: 自定义元素第一次被连接(挂载)到DOM 时调用;
- disconnectedCallback: 当自定义元素于DOM 文档断开连接时调用;
- adoptedCallback: 当自定义元素被移动到新文档时被调用
- attributeChangedCallback: 当自定义元素的一个属性被增加、移除或更改时被调用
MDN 官方生命周期使用DEMO life-cycle-callbacks