定义
浏览器原生支持的一套组件封装技术。这里有两个关键字:
- 组件技术
- 浏览器原生
组件化一直是前端完善的方向,从早期jquery组件(easyui),到现在vue组件(elementUI,Vant等),不管如何进步,本质上还是在组合HTML的 input,button,a等等的标签。
但Web Componets除了组合外:
- 不单能让你创建新标签
- 还能让你去扩展这些标签。
技术组成
Custom elements(自定义元素):一组JavaScript API,允许您定义custom elements及其行为,然后可以在您的用户界面中按照需要使用它们。
HTML templates(HTML模板): <template> 和 <slot> 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。
Shadow DOM(影子DOM):一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
定义&注册&使用
前面我们说了,支持定义和扩展两种方式,具体体现在代码上:
完全自定义模式:
定义:class PopUpInfo extends HTMLElement
注册:customElements.define('popup-info', PopUpInfo);
使用:<popup-info></popup-info>
扩展模式:
定义: class ExpandingList extends HTMLUListElement
注册:customElements.define('expanding-list', ExpandingList, { extends: 'ul' });
使用:<ul is="expanding-list">
有图例子中,定义和注册都在main.js,使用则直接在html上
image.png
生命周期
- connectedCallback:当 custom element首次被插入文档DOM时,被调用。
- disconnectedCallback:当 custom element从文档DOM中删除时,被调用。
- adoptedCallback:当 custom element被移动到新的文档时,被调用。
- attributeChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用。
首次加载时的处理,会调用connectedCallback
如果想监听属性的变化,触发attributeChangedCallback(name, oldValue, newValue),
还需要先监听属性,类似vue的Watcher:
static get observedAttributes() {
return ['attr1', 'attr2'];
}
Demo
class PopUpInfo extends HTMLElement {
constructor() {
// Always call super first in constructor
super();
// Create a shadow root
const shadow = this.attachShadow({mode: 'open'});
// Create spans
const wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
const icon = document.createElement('span');
icon.setAttribute('class', 'icon');
icon.setAttribute('tabindex', 0);
略。。。。
wrapper.appendChild(icon);
}
}
// Define the new element
customElements.define('popup-info', PopUpInfo);
createElement的方式,如果文档比较多怎么办?
模板
1,在html中定义template,同样也有类似的slot概念
<template id="my-paragraph">
<style>
p {
color: white;
background-color: #666;
padding: 5px;
}
</style>
<p>
<slot name="my-text">My default text</slot>
</p>
</template>
2,在组件中:
const template = document.getElementById('my-paragraph');
const templateContent = template.content;
this.attachShadow({mode: 'open'}).appendChild(
templateContent.cloneNode(true)
);
Shadow Dom
Shadow Dom可以说是该技术的精华。
组件封装我们一直追求样式隔离,脚本隔离。
比如:
样式的scoped
Window的代理以及备份还原
而Shadow Dom是天然隔离的,也就是说,组件内的样式,对象只在组件内有效。有点iframe的感觉。
image.png优缺点以及应用场景
我们总结一下它的优点:
浏览器标准
可以扩展HTML标签
天然各种隔离,真正的组件化
对单元测试友好
哪有没有短板呢?
- 交互
- 兼容性
- 公共性
其实从Web Components提出到现在已经近8年。在该套理论体系下,诞生了三大框架。
现在不能不讨论的就是,该组件和三大框架组件库(比如ElementUI)是一个什么样的关系?
- 目前从项目维度来看,Web Components还不是首选
- 对旧代码的兼容上近乎为0,只适用于新项目
- 由于自带沙箱,在iframe的替代场景上,有一定的期待
- 由于最近sveltejs发展比较迅速,在轻量级页面上,可以采用sveltejs+wc的方式
网友评论