Web Components
Web Components是一系列技术的组成。旨在解决页面代码复用的问题。
主要由三项技术组成:
- Custom Elements
- Shadow DOM
- HTML template & slot
Custom ELements - 自定义元素
自定义元素提供了定义元素行为和注册的接口。
CustomElementRegistry
通过 CustomElementRegistry 实例的 define() 方法定义 自定义元素。window上天然的提供了一个实例 - customElements 。
自定义元素分为两种。
Autonomous custom elements - 独立的元素
class CustomElement extends HTMLElement {
constructor() {
super()
const div = document.createElement('div')
div.textContent = 'This is a custom element.'
console.log(this)
this.appendChild(div)
}
}
customElements.define('custom-element', CustomElement)
<custom-element></custom-element>
如示例展示的一般, 独立的元素通过customElements.define注册后具体的类之后即可直接使用**<custom-element>**。
Customized built-in elements - 定制的内置元素
class LogButton extends HTMLButtonElement {
constructor() {
super()
this.addEventListener('click', () => {
const log = document.createElement('div')
log.textContent = 'log:' + new Date()
document.body.appendChild(log)
})
}
}
customElements.define('log-button', LogButton, { extends: 'button' })
<button is="log-button">print</button>
定制的内置元素在使用define方法时会额外多一个选项,同时实现的类是继承自扩展的元素类,而不是基本的HTMLElement。
在使用方法上,则是在原生元素上使用is属性来指定使用哪个定制的内置元素。
Shadow DOM - 影子DOM
在上文的示例中, 所有的DOM都是直白的展开在自定义元素内。也就是在主文档上,而组件化有一个很大的特性就是具有私有化。
Shadow DOM 就可以用来实现这一目的。
class CustomElement extends HTMLElement {
constructor() {
super()
const shadowRoot = this.attachShadow({mode: 'open'})
const div = document.createElement('div')
div.textContent = 'This is a custom element.'
console.log(this)
this.appendChild(div)
}
}
customElements.define('custom-element', CustomElement)
通过 attachShadow() 方法来获取当前自定义元素的 shadow dom root元素, 当使用了ShadowDOM后,之前填充在<custom-element>的内容就无法再显示出来,这个时候需要去填充Shadow DOM的内容。
而Shadow DOM可以有自己的style节点。所有它可以拥有自己独立的样式与节点。
HTML template & Slot
无论是自定义元素还是影子DOM都是一组JS接口,它们描述 UI(文档)的能力很差。
<template>
template标签的元素不会呈现在文档上,它拥有自己独立的document fragment节点。
这样就可以提前在html上提前描述好ui,然后通过复制template的节点到自定义元素中进行呈现。
<slot>
slot 是一个占位符,有了slot, Web Components更加灵活。例如一个展示文档的组件, 在自定义元素中留下了title,content等<slot>占位符。
在使用组建的时候 只需要使用slot包裹对应的元素就可以让它们填充占位符的内容。
优势
- 原生支持,无依赖,简单易上手
- 非侵入式,具有良好的私有性
劣势
- 描述ui的能力不强。
- API 相对成熟的框架 是低级和简单的。 对于逻辑和ui处理更加复杂。
- 各个浏览器兼容性不同
使用场景
- 组件库
- 跨端