在Web开发组件化的今天,React、Angular,Vue等主流框架都支持组件化的开发。Web Components的出现,使得浏览器可以原生支持组件化的开发。目前Web Components的支持程度如下图:
通过Web Components,我们可以封装自己的html、js、css,不必担心会影响到其他页面。下面通过一个自己定义的文件上传按钮来展示如何创建一个Web Components。
1. 创建Web Components
首先,我们需要定义一个类并继承自HtmlElement。
//define web component
class MyFileInput extends HTMLElement {
constructor() {
super();
const template = document.getElementById('myFileInputTemplate');
const templateContent = template.content;
//方法给指定的元素挂载一个Shadow DOM,并且返回它的 ShadowRoot.
//open 指定为开放的封装模式。
//closed 指定为关闭的封装模式。
//如果你将一个 Shadow root 添加到一个 Custom element
//将mode设置为closed,那么就不可以在外部获取 Shadow DOM了——myCustomElem.shadowRoot 将会返回 null。
this.attachShadow({ mode: 'open' }).appendChild(
templateContent.cloneNode(true)
);
}
}
在构造函数中获取了我们自定义元素的模板内容,并为元素挂载一个Shadow DOM。同时将模板内容添加到了Shadow DOM中。
定义好元素后,我们需要先注册自定义的元素,然后才能使用。通过window.customElements.define来注册元素,该方法的定一个参数可以指定元素的标签名称。
//register web componnet
window.customElements.define('my-file-input', MyFileInput);
然后就可以通过以下方式使用该自定义元素:
<my-file-input id="myFileInput">
<span slot="btnText">
Browse
</span>
</my-file-input>
HTML模板的定义如下:
<template id="myFileInputTemplate">
<style>
:host {
font-family: Helvetica, sans-serif;
}
.btn-browser {
position: relative;
display: inline-block;
line-height: 30px;
text-decoration: none;
text-align: center;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
padding: 6px 12px;
font-size: 14px;
color: #fff;
background-color: #337ab7;
border-color: #2e6da4;
}
input[type="file"] {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
font-size: 100px;
cursor: pointer;
}
</style>
<div class="my-input-container">
<a href="javascript:;" class="btn-browser">
<input type="file" />
<slot name="btnText"></slot>
</a>
</div>
</template>
在HTML模板中,可以定义元素的样式,元素的HTML内容。 :host代表元素本身。
2. slot 插槽
在上述的模板中,可以看到按钮的文本是通过插槽的方式填充到元素中的。通过插槽,可以将自己的HTML内容插入到Web Components的指定位置。
创建name为btnText的插槽:
<span slot="btnText">
Browse
</span>
引用了name为btnText的插槽:
<slot name="btnText"></slot>
3. Web Components 生命周期函数
Web Components包含以下生命周期函数:
- connectedCallback: 当自定义元素第一次被加入到文档时被调用。
- disconnectedCallback: 当自定义元素与文档DOM断开连接时被调用。(从文档中移除)
- adoptedCallback: 当自定义元素被移动到新文档时被调用。(调用adoptNode方法)
- attributeChangedCallback: 当自定义元素的一个属性被增加、移除或更改时被调用。
connectedCallback() {
console.log('connected');
}
//will trigger if element is removed
disconnectedCallback() {
console.log('disconnected');
}
//tirgger if adoptNode is called
adoptedCallback() {
}
attributeChangedCallback(attrName, oldVal, newVal) {
console.log(arguments);
}
以上。