shadow DOM
組件開發(fā)者編寫的 DOM项戴。Shadow DOM 對(duì)組件來說是本地的形帮,它定義了它的內(nèi)部結(jié)構(gòu)、作用域 CSS周叮,并封裝了實(shí)現(xiàn)細(xì)節(jié)辩撑。它還可以定義如何呈現(xiàn)由組件的使用者編寫的 DOM。
light DOM
由組件使用者編寫的 DOM仿耽。這個(gè) DOM 存在于組件的 shadow DOM 之外合冀。它是自定義元素的實(shí)際子元素。特別是 slot项贺。
插槽允許組件使用者定義 html君躺,因?yàn)椴皇?shadow DOM 的一部分,沒有被封裝开缎,所以樣式受頁面的影響棕叫,并且 DOM 可以被獲取到。比如下面 img 和 span 就是 light DOM:
<webc-button>
<img src slot="icon" />
<span> Hello </span>
</webc-button>
Lifecycle Events
一圖勝千言
Constructor
創(chuàng)建 webc 時(shí)調(diào)用奕删。
- HTMLElement 類建立原型鏈的地方
- 初始化組件必要的屬性
- 使用 attachShadow() 方法創(chuàng)建 shadow DOM
其余操作俺泣,比如獲取數(shù)據(jù)、渲染不建議在這里完残,而是在 connectedCallback 中
connectedCallback
每次 web 組件連接到 DOM 時(shí)調(diào)用伏钠。適合獲取數(shù)據(jù)或添加事件監(jiān)聽器。
adoptedCallback
每次將 Web 組件移動(dòng)到新文檔時(shí)調(diào)用谨设。這特別適用于 iFrame熟掂。
attributeChangedCallback
每次添加、更改或刪除 web 組件的屬性時(shí)調(diào)用铝宵。
接收三個(gè)參數(shù):
- 屬性名
- 舊值
- 新值
attributeChangedCallback(name, oldValue, newValue) {
}
要能夠監(jiān)聽到屬性的變化打掘,需要 observedAttributes 方法指定要監(jiān)聽的屬性。
static get observedAttributes() {
return ['value', 'min', 'max'];
}
disconnectedCallback
Web 組件與文檔 DOM 斷開連接時(shí)調(diào)用鹏秋。適合移除事件監(jiān)聽器尊蚁,中斷數(shù)據(jù)的請(qǐng)求等操作。
Custom Events
當(dāng)我們基于用戶操作執(zhí)行代碼時(shí)侣夷,原生事件是我們必須在 Web 上添加交互性的主要方式:例如横朋,當(dāng)用戶單擊某處(單擊事件)時(shí)我們運(yùn)行一些程序,或者當(dāng)用戶輸入時(shí)驗(yàn)證值的合法性百拓。
同樣的琴锭,在開發(fā) web 組件時(shí)晰甚,不得不需要用到事件。因?yàn)椋菏录墙M建公共 API 的一部分决帖,某些事件觸發(fā)后的邏輯需要交給組件使用者處理厕九。比如:
- 什么時(shí)候加載完數(shù)據(jù)
- 值更改
- 內(nèi)部觸發(fā)的事件
創(chuàng)建自定義事件
使用 Event 構(gòu)造函數(shù)
const event = new Event('build')
ele.addEventListener('build', function (e) { ... }, false)
ele.dispatchEvent(event)
添加自定義數(shù)據(jù)
要向事件對(duì)象添加更多數(shù)據(jù),使用 customEvent地回,detail 屬性可用于傳遞自定義數(shù)據(jù)扁远。 例如:
const event = new CustomEvent('build', { 'detail': 22 })
ele.dispatchEvent(event)
組件庫建設(shè)
內(nèi)部使用純?cè)?API 搞了一套移動(dòng)端組件庫。大致羅列下一套組件庫需要做哪些工作:
布局適配刻像、主題
目前主流的組件庫在適配上基本采用的方式是:設(shè)置基準(zhǔn)值畅买,然后使用 rem 或 vw 或者兩者兼用的方式,開發(fā)時(shí)同時(shí)使用 px细睡,打包時(shí)使用 px2rem 的插件進(jìn)行處理谷羞。但是 webc 組件不同,css 被封裝到了 Shadow DOM 中溜徙,無法使用 px2rem 進(jìn)行修改湃缎。并且 webc 組件還要面臨使用者適配方案不一致的情況。
webc 適配方案
既然 webcomponents 的組件是已經(jīng)打包成了不可見的 shadow dom 了萌京,既然通過插件改不了 css 代碼雁歌,就需要一個(gè)變量和外部形成橋梁宏浩,css 變量就是低成本知残、便捷的選擇。事實(shí)上已經(jīng)有不少三方組件庫采用 css 變量實(shí)現(xiàn)主題的自定義比庄。
;(function (win) {
win.rwcFn = function () {
var oDoc = document.documentElement,
iW = oDoc.clientWidth || win.innerWidth,
_base = 375,
_maxW = 1024
iW = Math.min(iW, _maxW)
oDoc.style.setProperty('--webc-base-font', (iW / _base).toFixed(2))
}
rwcFn()
win.addEventListener('resize', rwcFn, false)
})(window)
@media (min-width: 320px) {
:root {
--webc-base-font: 0.8533333333333334;
}
}
@media (min-width: 360px) {
:root {
--webc-base-font: 0.96;
}
}
/*
iphone 678x
*/
@media (min-width: 375px) {
:root {
--webc-base-font: 1;
}
}
/*
iphone 678 plus
*/
@media (min-width: 414px) {
:root {
--webc-base-font: 1.104;
}
}
/*
ipad
*/
@media (min-width: 677px) {
:root {
--webc-base-font: 1.8053333333333332;
}
}
/*
ipad
*/
@media (min-width: 712px) {
:root {
--webc-base-font: 1.8986666666666667;
}
}
/*
ipad
*/
@media (min-width: 768px) {
:root {
--webc-base-font: 2.048;
}
}
代碼質(zhì)量
eslint求妹、prettier、husky
無障礙
單元測(cè)試
使用 @open-wc/testing 和 @web/test-runner 做單元測(cè)試
與 Vue & React 結(jié)合
打包構(gòu)建
使用 webpack
打包出一個(gè)全局 bundle佳窑,針對(duì)每個(gè)組件打包出一個(gè)單獨(dú)的包制恍,按需加載時(shí)只引入單獨(dú)的文件即可。
文檔建設(shè)
構(gòu)建部署
stencil
純?cè)_發(fā)存在不少問題神凑,
- 開發(fā)效率低下净神;比如 html 模版和樣式的編寫和維護(hù)、數(shù)據(jù)更新的讀取和監(jiān)聽溉委、事件的觸發(fā)鹃唯、slot 的監(jiān)聽等
- 整體架構(gòu)需要從 0 到 1 搭建
- 目標(biāo)文件的輸出
- 與其他框架的集成等諸多問題
stencil 是由 ionic 團(tuán)隊(duì)開發(fā)的用于開發(fā) web 組件庫的工具鏈,包括:框架集成瓣喊、靜態(tài)站點(diǎn)生成坡慌、單元測(cè)試等功能。