了解webComponent概念:
web component是浏览器环境提供的一些新的原生支持的api和模版,它是一套可以支持原生实现组件化的技术;具体涉及到Custom elements(自定义元素)、Shadow DOM(影子DOM)和HTML template(HTML模板)。提供了对布局视图封装能力,可以让DOM、CSSOM和JavaScript在局部环境中运行,使得局部CSS和DOM不会影响到全局。
和目前的前端框架中组件概念有何区别:
组件化的特点:
-
高内聚,低耦合
-
标记鲜明易维护
-
块状接口易扩展
框架组件化的特点:
-
高效复用
-
作用域及样式隔离
-
自定义开发
-
钩子函数(生命周期)
web component提供了:
1.Custom elements:自定义元素,通过使用对应的api,用户可以在不依赖框架的情况下,开发原生层面的自定义元素,最关键的是,它将包含独立的生命周期,以及提供了自定义属性的监听。这就意味着它也同样具备了较高的可操作性。
2.Shadow DOM:影子dom(最大的特点是不暴露给全局),你可以通过对应的api,将shadow dom附加给你的自定义元素,并控制其相关功能。利用shadow dom的特性,起到隔离的作用,使特性保密,不用再担心所编写的脚本及样式与文档其他部分冲突。
3.HTML模版:通过<template/>、<slot/>去实现内容分发。
看着好像并没有太大区别,框架有的特点web component也有,web component同样可以满足我们对组件的自定义及复用、与文档其他部分隔离、生命周期的钩子函数,甚至是内容分发等这些诉求。甚至更优一筹,框架在浏览器原生规则之上又一层较高程度的封装,在带来便利高效的同时,不可避免的导致性能的下降。
如何开发一个web component?
一个web component就是一个我们可以在正常dom中使用的自定义元素。自定义元素只需要包含标记结构、样式以及脚本三个部分,最后再对新的自定义元素进行一个注册。简短demo如下:
<body>
<element-a></element-a>
<script>
class ElementA extends HTMLElement {
constructor() {
// 必须首先调用 super 方法
super();
// 元素的功能代码写在这里
// 在自定义元素中我们通过Element.attachShadow将一个shadow root附加到任意元素上:
const shadowRoot = this.attachShadow({ mode: 'open' })
// 参数mode有两个值
// open表示可以通过element.shadowRoot访问shadow-dom
// closed表示不可以从外部获取shadow dom(例如内置元素video)
// 接着我们就可以为自定义元素添加内容:
const para = document.createElement('p')
para.innerHTML = '这是我的自定义元素'
shadowRoot.appendChild(para)
// 创建style元素
const style = document.createElement('style');
style.textContent = `
p {
color: #ccc;
}
`
shadowRoot.appendChild(style)
}
connectedCallback() {
// 自定义元素首次插入文档dom时调用
// 相较于constructor只会执行一次,这个生命周期每次将节点连接到dom时都会调用
// 可能会执行多次(比如同一个自定义元素remove, append多次)
}
disconnectedCallback() {
// 自定义元素从文档中删除时,调用
}
adoptedCallback() {
// 自定义元素移动到新的文档
// 比如使用 adoptNode 方法在多iframe下移动元素
}
attributeChangedCallback(name, oldVal, newVal) {
// 属性变更时调用:三个参数对应属性名,旧值,新值
}
}
customElements.define('element-a', ElementA)
//可以看到define函数包含三个参数:
// 1.自定义元素名
// 2.包含自定义元素内容的类
// 3.可选参数,包含extends属性的对象,指定了创建的元素继承自哪个内置元素,可以继承任意的内置元素
// 第三个可选参数,需要解释下,我们注册的自定义元素分为两类。
// 第一种是独立的元素,不继承其他内置的html元素,此时,define函数不传递第三个参数,元素的类继承自HTMLElment类。这样注册的自定义元素,使用方式简单,像普通的html元素一样,例如:<element-a />
// 第二种是继承自某个内置的html元素,例如p。此时,第三个参数应该是{ extends: 'p' }。同时元素的类也应该继承HTMLParagraphElement类。使用方式是<p is="element-a" />或者在js中document.createElement("p", { is: "element-a" })。
</script>
</body>
在自定义元素类中定义内容需要借助shadow-dom接口的能力,它提供了封装的能力,将标记结构、样式和行为隐藏到一个独立的dom中,我们操作shdaow-dom和操作常规dom一样(新添加子节点、修改属性等),但是在shadow-dom中的元素和外部的元素互不影响,不能通过document.querySelector方法拿到内部的元素,外部的css样式也不会影响shadow-dom中定义的元素。我们会在里面定义自定义元素的结构,最后将其附加到常规的dom树中。
浏览器内置的一些html元素也有使用它的功能,例如:video input-range等,在 Chrome 中,开发者可以启用开发者工具的Show user agent shadow DOM选项,就能看到这些隐藏的结构。



从上可以看出web component的优点还是挺多的:
1.不依赖任何框架,在任何生态中都能运行良好
2.可以在任何一种框架中使用,不用加载任何模块、代码量小
3.易于继承,不需要编译
5.真正的局部CSS作用域
6.在主流浏览器上的支持已经极其良好
同时也会相应的存在一些缺陷:
这里浅谈,就不用demo赘述了
1、组件内部事件回掉
例如,一个弹窗组件中的确定按钮,它的事件是如何触发的呢?
现在方案是 custom element 内部自定义事件 new CustomEvent(),外部用 addEventListener监听,仿佛又回到了原生 JS 写应用的时代
2、组件样式覆盖
对于开发者来说,难免会遇到需要调整组件内部样式的时候。无论你是使用antd、vant还是使用其它组件库,但 web component 的 CSS 防污染机制导致你很难修改内部样式。这需要你付出一些代价来变相的修改内部样式
3、组件内部资源相对路径问题
4、form表单类组件 value 获取问题
Shadow DOM 中包含有 <input>、<textarea> 或 <select> 等标签的 value 不会在 form 表单中自动关联。
5.缺少数据绑定和状态管理也是 WC 存在的缺陷
1081

被折叠的 条评论
为什么被折叠?



