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