很早我们就可以在 HTML 文档中写 <custome-element></custom-element>
这样的自定义名称标签。但是浏览器对于不认识的标签一律当成一个普通的行内元素处理,没有相关语义。虽然我们能用 JavaScript 代码给它添加一些功能,但是并没有生命周期相关的函数供我们做一些初始化和销毁的处理。
通过浏览器提供的 Custom elements api 我们能定义一个自定义元素,并且告知 HTML 解析器如何正确地构造一个元素,以及在该元素的属性变化时执行相应的处理。
定义新元素
比如我们想要像 <date-string ln="zh"></data-string>
这样使用一个显示日期字符串的标签,并且在 ln 属性为 zh 时显示中文格式,en 时显示英文格式。
首先我们定义一个类 DateString 派生自 HTMLElement。
class DateString extends HTMLElement {
constructor() {
super()
return
}
// 返回需要监听的属性,当属性值改变的时候会调用 attributeChangedCallback 这个方法
static get observedAttributes () {
return ['ln']
}
attributeChangedCallback (name, oldValue, newValue) {
this.updateRendering (newValue)
}
// 元素插入到文档中时调用
connectedCallback() {
const ln = this.getAttribute('ln')
this.updateRendering(ln)
}
// 元素从文档中移除时调用
disconnectedCallback () {
window.clearInterval(this.interval)
}
updateRendering (ln = 'zh') {
// 一个比较好的实践就是在渲染时,检查元素的 ownerDocument.defaultView, 如果不存在则什么都不干
if (!this.ownerDocument.defaultView) {
return
}
if (this.interval) {
window.clearInterval(this.interval)
}
this.interval = setInterval(() => {
if (ln === 'zh') {
this.innerHTML = new Date().toLocaleString()
} else {
this.innerHTML = new Date().toString()
}
}, 1000)
}
}
然后调用 customElements.define