經過使用 Custom Elements 建立內聯的 CSS 和 JavaScript 的自定義元素。須要說明的是它不是 React, Vue 或者 Angular 的框架的替代方案,它是一個全新的概念。javascript
在 window 全局對象下暴露了 customElements 屬性,能夠經過此屬性訪問到 CustomElementRegistry
對象。 CustomElementRegistry
對象下的幾種方法用於註冊 Custom Elements和查詢 Custom Elements:css
define()
用於定義新的 Custom Elementget()
用於獲取 Custom Element 的 constructor,若是不存在,返回 undefinedupgrade()
用於升級 Custom ElementwhenDefined()
用於獲取 Custom Element 的 constructor,相似 get(),不一樣之處是返回值是 promise,有可用值是返回 resolves 狀態在調用 window.customElements.define()
方法前,首先要定義一個新的HTML元素html
class CustomTitle extends HTMLElement {
// ToDo...
}
複製代碼
在 CustomTitle 類的構造器中使用 Shadow DOM 關聯自定義 CSS,JavaScript 和 HTML到新的元素,這樣就能夠在這個新元素中封裝各類功能,首先初始化構造器java
class CustomTitle extends HTMLElement {
constructor() {
super()
//...
}
}
複製代碼
而後調用 attachShadow(),傳入參數 { mode: 'open' }
,這個屬性設置了 shadow DOM的封裝模式,若是設置值爲 open
,能夠訪問元素的 shadowRoot 屬性,若是值爲 close
,則不能夠。git
class CustomTitle extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
//...
}
}
複製代碼
接下來設置元素的HTMLes6
class CustomTitle extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.innerHTML = ` <h1>Hello WC!</h1> `
}
}
複製代碼
這裏的 innerHTML 能夠寫入多個 html taggithub
定義了內置元素後,便可使用 window.customElementsweb
window.customElements.define('custom-title', CustomTitle)
複製代碼
以上便可在頁面中使用 數組
class CustomTitle extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.innerHTML = ` <style> h1 { font-size: 40px; color: #000; } </style> <h1>Hello WC!</h1> `
}
}
複製代碼
window.customElements.define('custom-title', class extends HTMLElement {
constructor() {
...
}
})
複製代碼
在加入JavaScript處理方式上與 CSS 上略有區別,不能再模板字符串中直接寫入,須要加入 addEventListener處理promise
class CustomTitle extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.innerHTML = ` <style> h1 { font-size: 40px; color: #000; } </style> <h1>Hello WC!</h1> `
this.addEventListener('click', e => {
console.log('clicked')
})
}
}
複製代碼
可使用 template
,經過id指定到
<template id="custom-title-template">
<style> h1 { font-size: 40px; color: #000; } </style>
<h1>Hello WC!</h1>
</template>
<custom-title></custom-title>
複製代碼
而後在 Custom Element 構造器中引用到 shadow DOM 上
class CustomTitle extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
const tmpl = ducument.querySelector('#custom-title-template')
this.shadowRoot.appendChild(tmpl.content.cloneNode(true))
}
}
window.customElements.define('custom-title', CustomTitle)
複製代碼
除 constructor 外,還能夠定義生命週期函數,用於在特定時期執行特定的方法
connectedCallback
當元素插入到DOM中時執行disconnectedCallback
當DOM中刪除元素時執行attributeChangedCallback
當檢測到屬性發生更改或添加或刪除時執行(傳入3個參數)
adoptedCallback
當元素已移至新文檔時class CustomTitle extends HTMLElement {
constructor() {
//...
}
connectedCallback() {
//...
}
disconnectedCallback() {
//...
}
attributeChangedCallback(attrName, oldVal, newVal) {
//...
}
}
複製代碼
上面提到attributeChangedCallback
會監聽屬性值的變化,這裏要定義監聽屬性值的範圍,必須定義一個靜態方法用於返回監聽屬性的數組
class CustomTitle extends HTMLELement {
constructor() {
//...
}
static get observedAttributes() {
return ['diabled']
}
attributeChangedCallback() {
//...
}
}
複製代碼
這裏我定義了 disabled
屬性用於被監聽,當它的值變化了,好比它的值爲 true
document.querySelector('custom-title').disabled = true
複製代碼
此時,attributeChangedCallback
被觸發,三個參數值分別爲 'disabled', false, true
在自定義元素上定義自定義屬性,經過添加 getter 和 setter 函數向自定義元素上定義自定義屬性
class CustomTitle extends HTMLElement {
static get observedAttributes() {
return ['nbattribute']
}
get nbattribute() {
return this.getAttribute('nbattribute')
}
set nbattribute(value) {
this.setAttribute('nbattribute', value)
}
}
複製代碼
若是是定義相似 disabled
這樣的布爾屬性值,若是值爲 true
時展現這個屬性值,false
時不展現
class CustomTitle extends HTMLElement {
static get observedAttributes() {
return ['boolattribute']
}
get boolattribute() {
return this.hasAttribute('boolattribute')
}
set boolattribute(value) {
if (value) {
this.setAttribute('boolattribute', '')
} else {
this.removeAttribute('boolattribute')
}
}
}
複製代碼
在頁面加載過程當中,JavaScript的加載須要時間,此時自定義元素還未定義,當頁面加載完成後,頁面的的從新佈局過程可能不是那麼友好,爲了解決這個問題,加入 :not(:defined)
僞類,設置一個大體的高度和漸變效果
custom-title:not(:defined) {
display: block;
height: 400px;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
複製代碼
最新版的 FireFox,Safari,Chrome,使用 Chromium內核 重寫的Edge,IE(就別想了),另外能夠加入 polyfill 兼容老版本的瀏覽器
所謂定製化功能的內質元素是指對 HTML 中已存在的元素進行定製化功能,對已存在的元素進行功能擴展。在原有的元素上掛上構造器,生命週期鉤子等功能特性。 建立定製的內置元素與徹底定製化的元素不一樣,區別在如下列子,接下來要對 Button 作功能擴展,首先須要定義一個類,繼承的不是 HTMLElement 而是 HTMLButtonElement
class PlasticButton extends HTMLButtonElement {
constructor() {
super()
this.addEventListener('click', e => {
// Do something
})
}
}
// 在定義自定義元素時,須要加入 extends 參數
customElement.define('plastic-button', PlasticButton, { extends: 'button' })
複製代碼
在使用也有不一樣之處,在原有元素上使用 is 屬性指定擴展的元素
<button is="plastic-button"></button>
複製代碼
最新版的 FireFox,Safari,Chrome,使用 Chromium內核 重寫的Edge,IE(就別想了),另外能夠加入 polyfill 兼容老版本的瀏覽器