Web Components
创建可复用的dom元素,不限制任何框架中应用 MDN
由
Custom elements(自定义标签)
、Shadow DOM(影子DOM)
、HTML templates(HTML模板)
技术组成
均不支持IE,不支持旧版本edge, 部分移动端浏览器也不支持. 但可以 polyfill 后支持使用
Web Components是有能力以组件加载的方式将微应用整合在一起作为微前端的一种手段,目前暂未这块的解决方案
三项技术组成
旨在解决复用性的问题
Custom elements(自定义标签)
通过一组原生的api(
CustomElementRegistry
、CustomElementRegistry.define()
),定义原生的DOM标签
- vue开发时如果引用一个非原生的Dom标签会抛出警告,需做如下配置:
js
// 用一个 `RegExp` 忽略所有“xxx-”开头的元素 仅在 2.5+ 支持
Vue.config.ignoredElements = [ /^xxx-/ ]
Shadow DOM(影子DOM)
将一个独立的 DOM 附加到一个元素上,该元素具备隔离外部样式的能力
html
<!-- shadow DOM示例 -->
<body>
<div id="p1">真实DOM span内容</div>
<div id="p2"></div>
<script>
// 给元素挂载一个Shadow DOM
let container = p2.attachShadow({ mode: 'open' }) // closed 时,外部js无法访问影子DOM根元素,shadowDOM.shadowRoot为null
// console.dir(shadowDOM.shadowRoot) // #shadow-root(open) 根元素
let div = document.createElement('div')
div.innerText = '影子DOM 中的内容'
container.appendChild(div)
// 给shadow中的span设置样式,发现并不会影响外层的DOM结构
let styleEl = document.createElement('style')
styleEl.textContent = `div { color: red; }`
container.appendChild(styleEl)
</script>
</body>
TIP
- video、iframe等都是shadow DOM的体现。
- shadow dom也可以使用原生的getElementById等api获取到
HTML template(HTML模板)
原生标签: <template> 、 <slot>
- 解析html时,写入该标签的内容不会被渲染。需手动操作插入到页面中,作为自定义元素结构的基础被多次复用
原生组件template不足点
缺少MVVM架构支持,无双向数据绑定
原生的api写法触发事件
缺少强大的组件整合机制,例如:slot(插槽)的作用域
js
// 组件内部使用 CustomEvent 自定义事件,并触发
class myDialog extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' })
shadowRoot.innerHTML = `
<div class="dialog">
// 弹窗内容
<button id="btn">确定</button>
</div>
</div>
`;
shadowRoot.querySelector('#btn').addEventListener('click', () => {
// 组件内部定义事件
this.dispatchEvent(new CustomEvent('btn-event', { params: 'test' }))
})
}
}
customElements.define('my-dialog', myDialog)
js
// 外部监听
document.addEventListener('btn-event', function(params){
console.log(params) // { params: 'test' }
})