Web Components - 面向未來的組件標準
首先需要說明的是這不是一篇 Web Components 的科普文章,如果對此了解不多推薦先讀《A Guide to Web Components》。 有句古話-“授人以魚,不如授人以漁”,如果把組件比作“魚”的話,對于前端開發者而言,W3C組織制定的HTML標準以及瀏覽器廠商的實現都是“魚”而 不是“漁”,開發者在需求無法滿足的情況下通過現有技術創造了各種組件,雖然短期滿足了需求但是由于嚴重缺乏標準,導致同一個組件有成千上萬的相似實現但 它們卻無法相互重用,這很大程度上制約了組件化的***價值-重用,Web Components則在組件標準化方面向前邁了一大步。
現狀與困境
組件化給前端開發帶來了極大的效率提升,組件化的UI框架也因此層出不窮,從EXTJs、YUI到 jQuery UI ,再到 Bootstrap、React、Ratchet、Ionic等等等等等等,幾乎每年都有很多新的UI框架冒出來,它們或者借鑒或者顛覆其他已存在的框架。簡單對比一下就會發現這些框架的很大一部分模塊在功能上是重合的,但也僅僅在功能層面重合,代碼層面確完全不兼容。
接下來選擇 jQuery UI、KendoUI 以及 Bootstrap 中的Dialog
組件從初始化、方法調用以及事件響應方面進行簡單的對比。
jQuery UI
- // 初始化
- $( "#dialog" ).dialog({
- dialogClass: "no-close"
- });
- // 顯示
- $( ".selector" ).dialog({ show: { effect: "blind", duration: 800 } });
- // 關閉事件
- $( ".selector" ).on( "dialogclose", function (e, ui) {
- // do something...
- });
Kendo UI
- // 初始化
- $("#dialog").kendoWindow({
- actions: [ "Minimize", "Maximize" ]
- });
- // 顯示
- var dialog = $("#dialog").data("kendoWindow");
- dialog.open();
- // 關閉事件
- var dialog = $("#dialog").data("kendoWindow");
- dialog.bind("close", function (e) {
- // do something...
- });
Bootstrap
- // 初始化
- $('#myModal').modal({
- keyboard: false
- });
- // 顯示
- $('#myModal').modal('show');
- // 關閉事件
- $('#myModal').on('hidden.bs.modal', function (e) {
- // do something...
- });
簡單對比可以發現,幾乎完全相同的功能在接口層面完全不兼容,導致使用者從某個實現切換到另一個實現時需要非常高的成本,這就是目前Web組件化方面無序和缺乏標準的一個寫照。
再來看目前瀏覽器“內置”組件的現狀,由標準化組織建立 HTML4、HTML5 等各種標準,瀏覽器廠商按照標準實現“內置”組件并聲稱兼容某某標準,開發者遵循標準來使用組件,使得代碼可以在不同的瀏覽器里通過相同的方式來使用組件。
以“內置”組件video
來簡單示例:
- // 初始化(直接寫<video>標簽或者通過javascript創建)
- var video = document.createElement('video');
- // 播放
- video.play();
- // 播放事件
- video.addEventListener("play", function () {
- // do something...
- }, false);
相比使用各種組件框架來說,“內置”組件也是由不同的開發者(瀏覽器廠商)開發,但是由于遵循了相同的標準使得“內置”組件的使用在跨瀏覽器方面的成本大幅降低。
綜上所述,組件框架目前無序、缺乏標準以及低效復用方面的問題需要通過組件標準化來解決,而Web Components則是標準化的一個很好的選擇。
面向未來的組件標準
Web Components 的出現給組件標準化帶來了很好的契機:
- WEB組件目前仍然依靠各種類似"Hack"的方式來模擬,模擬方式也各有不同,很難統一和標準化,而 Web Components 則直接提供了標準化的組件定義方式,這是組件標準化的基石,使得未來的組件能夠統一創建、方法調用、事件監聽、屬性訪問等。
- 基于標準化的組件定義方式,我們便可以像W3C等標準組織一樣來定義組件標準,無需再依賴、等待“內置”組件,這也使得我們獲得了“漁”的能力。
以上述的例子為例,未來可能會有一小撮人成立某個組件標準化組織-X,X的職責就是根據WEB組件的使用現狀以及潛在的新需求來規范一個組件,包括組件的名稱、方法、屬性、事件。
例如《Dialog規范1.0》
- 組件名:x-dialog
- 屬性:title
- 方法:show hide
- 事件:hide show
隨后出現的UI框架宣稱支持《Dialog規范》,但在實現上完全沒有制約,可以是完全不同的實現方式、或者更好的性能、更炫的UI,而對于開發者而言,只需要寫如下代碼即可:
- // 初始化(<x-dialog/>或者如下代碼)
- var dialog = document.createElement('x-dialog');
- // 獲取和設置title
- var title = dialog.title;
- dialog.title = title + '-_-';
- // 顯示
- dialog.show();
- // 關閉事件
- dialog.addEventListener('hide', function( e ) {
- // do something...
- }, false);
當用戶不滿意某個 Dialog 的實現而需要切換到其他實現版本時只需要引入不同的實現庫,而不再需要重構代碼。
跨端的組件標準
集鵠在跨端組件實踐 - 移動時代的前端一文中提到了跨端組件的概念。
跨端組件的實現同樣面臨著標準化的問題,Web Components 的標準化只規范接口,而底層的實現是完全自由的,自由到你可以使用 Web 技術來實現也可以使用 Native技術。
同樣以 Dialog 為例,開發者可以在 Android 中用 Java 或者在 iOS 中用 Objective C 來開發聲稱兼容 《Dialog規范1.0》的組件,此時,Web 開發者的那段調用 Dialog 的代碼不僅僅在 瀏覽器環境有效,在 Native 依然有效,而且調用的是 Native 實現,能夠獲得更為出色的性能。
總結
回顧瀏覽器的發展歷史,也曾經歷混亂和無序,隨著W3C標準化組織的出現這一局面有了翻天覆地的變化,而對于Web組件而言,Web Components 的出現才僅僅是這一變化的開始,隨著更為復雜的多端環境的出現,組件標準化還有著更大的想象空間。