Web componentd元件內部事件回撥及痛點剖析
目錄
- 寫在前面
- WC 到底是什麼?
- 目前存在的缺陷
- 1、元件內部事件的回撥
- 2、元件樣式覆蓋
- 3、元件內部資源相對路徑問題
- 4、form表單類元件 value 獲取問題
- 5、其它
- 寫在後面
寫在前面
最近致力於研究 Web components(以下簡稱WC),並且也初有成效的拿到了一定的結果,但今天想回過頭來重新審視一下 WC。
WC 到底是什麼?
簡單的講,Web Component 就是把元件封裝成 html 標籤的形式,並且在使用時不需要寫額外的 程式碼。
元件是前端的發展方向,拋開周邊技術生態,單純看 React 和 都是元件框架。因此,WC 可以視為原生標籤的拓展/延伸,說到底,它依舊是一個標籤!
類似<
標籤,相比於原生標籤,它多了更為豐富的樣式和可操作屬性。
谷歌公司由於掌握了 Chrome 瀏覽器,一直在推動瀏覽器的原生元件,即 Web Components API。
相比第三方框架,原生元件簡單直接,符合直覺,不用載入任何外部模組,程式碼量小。貌似一切完美,似乎大有可以用來替換React、Vue之類的趨勢。
目前存在的缺陷
與其它 web 框架一起使用存在一些小問題,會給開發體驗上造成一些困擾。
1、元件內部事件的回撥
比如,一個彈窗元件(<my-dialog></my-dialog>
)中的確定按鈕,那麼它的事件是如何觸發的呢?
class myDialog extends HTMLElement { // ... connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <div class="dialog"> <div class="dialog-content"> <div class="dialog-body"> 彈窗內容 </div> <button id="okBtn">確定</button> </div> </div> `; shadowRoot.querySelector('#okBtn').addEventListener('click',() => { // 元件內部定義事件 this.dispatchEvent(new CustomEvent('okBtnFn')); }); } } customElements.define('my-dialog',myDialog);
現在方案是 custom element 內部自定義事件new CustomEvent()
,外部用addEventListener
監聽。這樣的寫法是很醜陋的,彷彿又回到了原生 JS 寫應用的時代。
<my-dialog></my-dialog> <script> export default { created() { document.addEventListener('okBtnFn',function(){ // 點選彈窗按鈕,www.cppcns.com觸發回撥事件 }); } } </script>
2、元件樣式覆蓋
對於開發者來說,難免會遇到需要調整元件內部樣式的時候。無論你是使用antd
、vant
還是使用其它元件庫,但 WC 的 防汙染機制導致你很難修改內部樣式。這需要你付出一些代價來變相的修改內部樣式
3、元件內部資源相對路徑問題
就目前來說,任何直接基於 Custom Element v1,Template 和 HTML Import 的元件都無法做到完全資源獨立 —— 在不知道使用方環境且不給使用方增加額外限制的情況下使用內部封裝的任何資原始檔。比如如果你有一個自定義 icon 元件:
class MyIcon extends HTMLElement {
static get observedAttributes() { return ['name','size','color'] }
construchttp://www.cppcns.comtor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024">
<use id="use"></use>
</svg>
}
attributeChangedCallback (name,oldValue,newValue) {
客棧 if( name == 'name' && this.shadowRoot){
// 如果使用的專案中,根目錄沒有 icon.svg 檔案,那就 gg
this.use.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href',`./icon.svg#icon-${newValue}`);
}
}
}
customElements.define('my-icon',MyIcon);
如果使用的專案中,根目錄沒有 icon.svg 檔案,那就 gg。如果你在這裡使用 cdn 路徑,就會出現跨域問題。
4、form表單類元件 value 獲取問題
Shadow DOM 中包含有 <input>、<textarea> 或 <select> 等標籤的 value 不會在 form 表單中自動關聯。
示例程式碼:
// web component class InputAge extends HTMLElement { constructor() { super(); } // connect component connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }); shadow.innerHTML = `<input type="number" placeholder="age" min="18" max="120" />`; } } // register component customElements.define( 'input-age',InputAge );
WC 元件被使用後
<form id="myform"> <input type="text" name="your-name" placeholder="name" /> <input-age name="your-age"></input-age> <button>submit</button> </form> <script> const form = document.getElementById('myform'); form.addEventListener('submit',e => { e.preventDefault(); console.log('Submitted data:'); const data = new FormData(form); for (let nv of data.entries()) { console.log(` ${ nv[0] }: ${ nv[1] }`); } }); </script>
提交的時候無法獲取input-age
的valwww.cppcns.comue
。當然會有解決方案,但會很複雜。
5、其它
此外,缺少資料繫結和狀態管理也是 WC 存在的缺陷,此處不再贅述。
寫在後面
WC 指在豐富 HTML 的 DOM 特性,讓 HTML 擁有更強大的複用能力
WC 可以直接當做原生標籤,在任何前端框架和無框架中執行
結合當下的主流技術棧來說,WC 當前主要問題在於複雜的元件中,資料通訊和事件傳遞存在一定使用成本
相容問題,比如可以覆蓋內部樣式的:part
方法
以上就是Web componentd元件內部事件回撥及痛點剖析的詳細內容,更多關於Web componentd事件回撥及痛點的資料請關注我們其它相關文章!