您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
由于最近作者在学习微前端,web component
也是其中一大特性,部分微前端框架使用到,也是深入学习了一下相关的知识,分享出来。
Web Component 实际上一系列技术的组合,主要包含 3 部分:
<template>
来定义组件模板,使用 <slot>
作为插槽使用(Vuer一定不陌生);在一份html文件中的一个web component
看起来是这样的:
<trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件"><div slot="slot-ele">插槽内容</div>
</trace-ele>
看起来很像Vue吧?接下来让我们一个个demo学习web component
。
由于Web Component
亲和原生,因此无需其他包的依赖,一个index.html
和一个index.js
即可体验学习。
我们直接写一个html模板,文章的案例组件统称为<trace-ele />
index.html:
<body><template id="trace"><div class="container"><imgclass="image"src=".webp"alt=""/><p class="title">学习Web Component</p><p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p><p class="price">¥25.00</p></div></template><trace-ele /><script src="./index.js" />
</body>
这里我们写了一个"模板"——template
,并在下面声明了<trace-ele />
组件。
而实现这一切的原理在index.js
中。
class Trace extends HTMLElement {constructor() {super();const templateEle = ElementById("trace");const cloneEle = t.cloneNode(true);this.appendChild(cloneEle);}
}customElements.define("trace-ele", Trace);
Web Component
组件本质是一个类继承于HTMLElement
,当customElements.define
声明完组件后,类中的this
指向于组件本身,打印结果如下:
在初始化时,需要提供给组件一个空壳,并且绑定template
元素的id,这样就出现组件效果了。
看到这里是不是感觉和Vue
很像呢?接下来我们继续升级组件的功能~
在上一节基础上,给组件上点样式,很简单,改变index.html
即可,在template
中加入style
:
<body><template id="trace"><div class="container"><imgclass="image"src=".webp"alt=""/><p class="title">学习Web Component</p><p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p><p class="price">¥25.00</p></div><style>.container {display: inline-flex;flex-direction: column;border-radius: 6px;border: 1px solid silver;padding: 16px;margin-right: 16px;}.image {border-radius: 6px;}.title {font-weight: 500;font-size: 16px;line-height: 22px;color: #222;margin-top: 14px;margin-bottom: 9px;}.desc {margin-bottom: 12px;line-height: 1;font-size: 14px;}.price {font-size: 14px;}</style></template><trace-ele /><script src="./index.js" />
</body>
样式生效:
但是这里如果给一个通用标签的样式,就像这样:
<body><p>组件外的P标签</p><template><p>组件中的P标签</p><style>p {color: red;}....container {}</style></template>
</body>
效果如下:
可以看到组件外的p标签
也被影响了,颜色变为红色,而在组件概念中这个样式其实只期望作用于组件本身。这也是样式隔离的概念,而很幸运,Web Component
提供了开箱即用的样式隔离方案。
为了不让 <template>
里的 <style>
CSS 和全局的 CSS 有冲突,我们可以将组件挂在到 Shadow Root 上,再用 Shadow Root 挂到外层的 document DOM 上,这样就可以实现 CSS 的隔离啦:
class Trace extends HTMLElement {constructor() {super();this.attachShadow({ mode: "open" });const templateEle = ElementById("trace");const cloneEle = t.cloneNode(true);this.shadowRoot.appendChild(cloneEle);}
}customElements.define("trace-ele", Trace);
从控制台中观察:
而如果有多个组件本质其实就是在document
中有多个Shadow Root
。
整个DOM架构图是这样的:
Shadow DOM 的一大优点是能将 DOM 结构、样式、行为与 Document DOM 隔离开,非常适合做组件的封装,因此它能成为 Web Component 的重要组成部分之一。
与Vue
、React
一样,Web Component
也提供了父传子的形式。
index.html:
<trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件">
这里传了3个props给组件,在组件中打印this
如下:
火眼金睛的我已经找到了在组件中接受传参的入口:
做一个简单的动态赋值:
class Trace extends HTMLElement {constructor() {super();this.attachShadow({ mode: "open" });const templateEle = ElementById("trace");const cloneEle = t.cloneNode(true);cloneEle.querySelector('.container > .title').textContent = Attribute('name');cloneEle.querySelector('.container > .price').textContent = Attribute('version');cloneEle.querySelector('.container > .desc').textContent = Attribute('desc');this.shadowRoot.appendChild(cloneEle);}
}customElements.define("trace-ele", Trace);
搞定~
HTML 模板的另一个好处是可以像 Vue
一样使用 <slot>
。比如,现在我们可以在这个 <trace-ele>
最下面添加一个插槽:
<body><template id="trace"><div class="container"><p>组件中的P标签</p><imgclass="image"src=".webp"alt=""/><p class="title">学习Web Component</p><p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p><p class="price">¥25.00</p><slot name="slot-ele"></slot></div><style>...</style></template><trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件"><div slot="slot-ele">插槽内容</div></trace-ele>
</body>
这样我们就可以实现自定义插槽内容了。
Web Component
也可以给组件中元素或者插槽绑定事件。
class Trace extends HTMLElement {constructor() {super();this.attachShadow({ mode: "open" });const templateEle = ElementById("trace");const cloneEle = t.cloneNode(true);cloneEle.querySelector(".container > .title").addEventListener("click", Click);this.shadowRoot.appendChild(cloneEle);}onClick = () => {alert("Click Me!");};
}customElements.define("trace-ele", Trace);
上面主要给大家分享了一下 Web Component 的一些使用方法。总的来说,Web Component 是一系列 API 的组合:
它看起来仿佛是现在主流框架的基建实现,框架也正是基于原生的能力实现出一整套的解决方案,就比如Vue的响应式以来追踪、模板语法数据绑定,都是我们希望看到的。
本文发布于:2024-02-04 11:09:51,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170705819955035.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |