這篇文章將從 AngularJS ReactJS Polymer 這幾個流行的框架入手,分析前端框架在這幾年發展中的關鍵技術點,做爲2015前端技術選型的參考。摘要:html
1. 初體驗前端
拿TODO來做爲引子好了.vue
Angular 的實現react
React的實現(非flux架構)git
Polymer的實現github
三者共同對比web
在Angular中有controller和component的概念是分離的,而react和polymer中只有component的概念。ajax
實際上三者在最簡單的使用場景下差別並不大,Angular和polymer模板和代碼分離的方式更貼近於傳統的前端作法,而React寫法更像後端渲染。關於學習和使用成本的誰高誰低得問題沒有什麼好爭論的,在MVVM已經流行了這麼久的狀況下,三者入門門檻都差很少,但要用好都須要深刻其中的運行機制才行。chrome
2. 技術特色後端
實際上所謂的MVVM框架的關鍵技術就一個:數據與視圖的綁定。在Angular/polymer/knockout/vue/avalon 中,這項技術的實現又能夠拆分紅兩個關鍵點:模板分析和數據監測。
模板分析的主要目的是對 {{title}} 這樣的標記進行收集。收集完成以後生成一個視圖更新函數,在函數內部保存着這個標記所在的Dom片斷和相關的數據名稱,函數被調用時會去從新取數據名稱對應的數據(或者由外部將相應的數據做爲參數傳入),而後更新dom片斷。這樣就實現了視圖的更新。通常框架會在啓動時就將模板分析完,生成相應的視圖更新函數。當數據更新的時候,就調用這些更新函數來更新視圖,那麼問題來了,如何檢測數據的改動?
knockout/angular/avalon表明了三種方案:
至此,兩個關鍵技術點都已講清楚,用一張圖來回顧一下
而在React中則相對簡單,React用的是相似於重繪的機制,當觸發了 setState 以後,就徹底從新渲染(並不是當即觸發,中間有相似於緩存的性能提高機制)。這看起來比起前面的方案簡單粗暴,可是卻由於virtual dom的實現化腐朽爲神奇了。virtual dom指的是React內部用來模擬真實dom的一種數據對象。當從新渲染時,其實是先生成這樣virtual dom,而後將其和上一次的virtual dom進行對比,找出差別,最後由react在真實的dom上更新有差別的部分就夠了。由於virtual dom始終在內存中,真實的dom操做很是少,而前面的幾種框架在更新視圖時經常會有大量的dom操做,所以react在性能上大大領先前一種類型的框架。同時也由於virtual dom仍然是標準的 js對象,因此使得"服務端渲染"也成爲可能。
值得注意的是,雖然React自己並不會像前面的框架同樣深刻的去檢測數據的哪一部分發生了變化,可是能夠經過官方提供的addon 和immutable.js來進一步提升這一塊的性能。
3. 組件化
在組件化的方向上 react 和其餘幾種框架幾乎已經分道揚鑣了。從 angular2.0的設計和新出的 aurelia 等框架中能夠看到你們都在嘗試往 webcomponent 靠近。polymer號稱下個版本代碼將大幅減小,那無非是由於瀏覽器將實現標準了。靠近 webcomponent 的好處在於任何一個框架都將再也不封閉,以 custom element做爲接口層,能實現生態圈的融合。
雖然 react 也有封裝成 custom element的方案,可是 react 並無很好的調用其餘框架生成的 custom element 的方案。"像使用原生dom元素同樣使用custom element"的組件使用方式意味着尊重原生的dom使用方式,包括dom的事件等等。這和react"不操做真實dom"的基礎已經方向相悖了。
react和其餘框架的分歧其實目前看來並沒有優劣之分,由於webcomponent目前除了chrome之外其餘瀏覽器支持仍然不全面。另外考慮到特殊國情的話,大公司的產品仍然要面對IE8。不幸的是目前polymer的polyfill最低也只到IE9。而React能無痛支持IE8。再考慮到移動端的瀏覽器狀況的話,也是使用react的技術阻力遠小於webcomponent。
整體來看,webcomponent確定會是趨勢,而且將促進各個框架變得更加開放,更易互相融合。而react也仍將繼續依靠本身在實現上的優點繼續走下去。也許將來在這中間又將誕生新東西。
暫時拋開react和webcomponent。咱們繼續深刻兩個目前討論得不多可是卻很重要的問題(下面討論的組件問題都以封裝成custom element爲基礎):
針對第一個問題,我所在的團隊目前提出一個叫作"模板複寫"的規則,這個規則又分爲"徹底重寫"和"部分重寫"兩種規則:
部分重寫
這種方案已在angular中實現。而且在組件重用率高的系統中已經驗證很是實用。但它也有缺陷,缺陷在於你必須知道當前組件的實現方式和原有模板才能複寫。
第二個問題,能夠用一種稱爲"共享做用域"的方式來解決。例如上面的例子中story沒有顯示like數量,如今要顯示出來。常規方案有兩種:
第一種方案可能碰到的問題是當再次發生變化,例如統計數據不要顯示在組件裏面了。就得繼續改爲第二種方案。 第二種方案可能碰到的問題是可能不斷有新的需求提出來,最後不得不把每個內部狀態都暴露出來,每個操做過程都拋出事件。
"做用域共享"共享的方案是: 經過在一個特殊標記 "import-to" 將某一段外部html引入到某個組件中去一塊兒參與"模板解析"和"數據綁定",當完成時再放回原來的位置。這樣這個外部html就能獲取到組件內部任何狀態和數據了。這種方案看起來有點像hack,但其實只是換了一種方式來理解組件:組件分紅兩個部分,一是數據,二是視圖。視圖理論上應該只受到它的邏輯是否足夠內聚的約束,而不該該受到它的子元素是否放在一塊兒的約束。可是目前咱們恰好使用了dom做爲視圖的基礎,因此視圖受到html結構的約束,這個約束是不合理的。咱們來用圖對比一下使用"做用域共享"先後的場景:
固然,這種方案的缺陷仍然是你必須知道組件的具體實現。但這並非一個不可克服的缺陷,咱們看下aurelia的設計,它將template等等關鍵部分都設計成了可插拔的形式,這種結構意味着將來有可能實現一種通用的模板語法來實現上述兩個功能。這樣就再也不和底層耦合。
4. 應用架構
應用架構的範圍太廣,咱們這裏只討論那些已經很好地組件化了的應用,或者是沒組件化可是有明確層級劃分的應用。咱們以React 對應的 FLUX 爲切入點。
咱們再來結合facebook的官方FLUX代碼示例來看看每一個部分:
facebook在介紹FLUX的時候的主要觀點是"MVC擴展性不夠,FLUX可擴展性高"。暫且不去討論FLUX與MVC的區別, 咱們先來它是如何擴展的,從上面的代碼中能夠看到,ACTION不僅是一個界面上的點擊事件所產生的,ajax請求、甚至一個初始化過程均可以產生動做,"動做"只是一個抽象。動做將傳遞給dispatcher,有dispatcher在去觸發store註冊的回調。你可能會想,從這個dispatcher實際上什麼也沒幹,這和我直接定義一個方法,觸發事件就直接調用這個方法有什麼區別?區別在於,當應用增長功能、進行擴展時,應用可能有多個部分要協同對同一個action進行響應,而且不一樣的協同部分可能在執行順序上有嚴格的前後之分。
舉個例子,若是我要對上面的TODO增長一個"統計區塊",若是是傳統的MVC寫法,你可能要新增一個statisticModel,而後在controller中的createTODO、deleteTODO中增長代碼來操做這個新的statisticModel。而FLUX不用修改已有的任何代碼,只須要寫新的store,並註冊一些回調到createAction、deleteAction中就夠了。因此能夠看作是將MVC中的 "C主動操做M" 反轉成 "M來決定什麼時候運行"(固然這種狀況也就沒有C了), 但更好的是理解成是一種"事件系統"的變種。這就是它和MVC的區別。嚴格來講 FLUX 並不能算是facebook"發明"出來的,這樣的模型在不少事件驅動的後端框架中很常見,如zero、yii,只不過拿到前端來做爲應用架構時比較新穎。
FLUX是目前高度推薦的應用架構方式,它並無強制使用的庫或者框架,因此並不侷限於react,在angular、polymer中一樣能自由實現。特別是目前angular、polymer中的應用開發並無一種應用架構的最佳實踐。angular中的模塊化既沒有異步加載也沒有做用域隔離的做用,實際使用時很雞肋。可是angular中的依賴注入、filter、service的設計很是全面,若是再能加上FLUX的架構的話,威力不容小覷。對polymer來講狀況更簡單,應爲polymer目前只考慮到element這一層,因此上層的應用架構能夠自由實現。
值得補充的是,FLUX中的store,dispatcher能夠更好地增強一下。store可使用一些自動支持REST的庫來簡化開發,dispatcher可使用支持自定義順序等高級的事件代理實現。
5. 總結
2015將是前端框架相互借鑑相互融合的一年,隨着webcomponent的落地,你們都在像標準靠近。提早儲備這方面的技術確定沒有問題。再深刻到框架的技術細節中,咱們看到在"渲染機制"、"數據綁定"、"組件化"、"模塊化"這些關鍵技術點中各個框架中都有很是精彩的實現,值得深刻學習。React異軍突起,也推薦持續關注,特別是在"應用架構"上,FLUX確實在整個業界起到了啓發的做用,相信會愈來愈流行,而且有愈來愈多實現方式。