Web Component杂谈
发布于
- 修改于
2021/11/23
- 大约需要 2 分钟
- 777 字
缘起
之前在写ScalaJS + React的时候,突然想到好像自己从没看过Vue的文档,遂去查看。看到一半看到了Web Component这个技术,也是听说已久从未见过的内容,遂去MDN查看文档。之后觉得还挺有趣,而且还是Web标准。
Web Component
这个标准的目的很简单,就是做到像React、Vue之类的框架中的组件复用。根据MDN文档,主要包括三部分:
- 自定义控件
- Shadow DOM
- template + slot
自定义控件就是做到像React+JSX那样可以<MyComponent></MyComponent>
;Shadow DOM则是允许将样式绑定在组件内部和组件封装,并根据开闭与否决定内部的是否可从外部访问,例如像<video>
那样自带一堆按钮等,但是从外面完全看不到细节;template则是允许制作模板,方便用时直接创建;slot则是允许将控件放在模板的内部,而不仅仅是通过传递属性来改变内容。
举例来说
<template id="temp">
<style>
:host p {
color: red
}
::slotted(p) {
color: green
}
</style>
<h1 part="head">Here's the header</h1>
<slot></slot>
<p>Here's the end</p>
<slot name="more"></slot>
</template>
<script>
customElements.define('my-component',
class extends HTMLElement {
constructor() {
super();
let template = document.getElementById('temp');
let templateContent = template.content;
const shadowRoot = this.attachShadow({ mode: 'closed' })
.appendChild(templateContent.cloneNode(true));
}
});
</script>
<my-component>
<p>Hello World</p>
<p>Hello Again</p>
<p slot="more">Or maybe there's more</p>
</my-component>
在这里我定义了一个模板及对应样式,定义了一个组件,并且往不命名插槽里扔了两个<p>
,往命名插槽里扔了一个<p>
,同时关闭了从外访问我组件内部元素的开关。我将原本的<p>
设为红色,插入的<p>
设为绿色,并保留了对于<h1>
的css修改的可能性——外部只需要用my-component::part(head)
作为选择器就可以修改这部分的样式。当然,模板不是必须的,我可以手动创建一个复杂的元素再接到shadowRoot上去。
可以看到Web Component作为Web标准的一部分的优点:使用简单,无需框架,没有依赖。当然,缺点也是有的,具体可以参考Vue的官方文档作的对比。