2013年最後的收成:avalon1.0正式發佈

大半年前我就說過,MVVM是前端究極的解決方案,所以以後我大多數時間都在折騰avalon,成立了專門的QQ羣與感興趣的一塊兒討論。感謝第一批吃螃蟹的人,avalon發展得很快,GITHUB上的貢獻人數達到8人,issues二百多個主題,各類組件也不斷完善。時至今日,我能夠自豪地說許多靜待1.0的看客說,它終於來了!javascript

下面是avalon的生態系統:php

avalon的核心是avalon.js或avalon.mobile.js(移動端版本,針對手機與平板)。其中avalon.js兼容到IE6,知足中國的特殊國情。avalon.mobile.js是支持移動端,IE10起支持,它使用了大量高級API,性能遠超avalon.js,並添加了觸屏事件的支持。css

而後是三柱臣:mmRouter, mmAnimate, mmRequest,單頁應用最經常使用的三個組件。html

接着是拖放,事件代理,組件鍵,驗證框架,高級定位機制,組合鍵等亂七八糟的,用於錦上添花的前端

最後是UI庫,比較簡單的控件都作出來,重頭的樹,GRID,多級菜單正在規劃中……java

說一下個人初衷啊。我最先是作企業級應用,大量的表單,大量的列表,迭代頻繁,雖然JQ已經出來了,但業務邏輯與DOM顯示邏輯混淆在一塊兒,維護起來很是不爽。因而我開發了ejs這個前端模板。前端模板在當前仍是一個很新的概念,所以我當時發佈在博客園,許多人不解。但比起在JS文件裏進行鎖碎的字符串拼接,它就是易讀易維護。QQ空間,淘寶那時也已經使用前端模板了。那是09年的事。以後,前端模板就像雨後春筍地不斷涌現,性能愈來愈高。react

轉輾到盛大創新院後,作圈樂這個視頻項目的瀑布流,與大牛們共事,用的是qwrap,接觸了許多新概念。個人框架由dom Framework改名mass Framework,大量精力耗在選擇器引擎與模塊加載器的開發上。那時requirejs也是剛剛起步, Sizzle也很粗糙,所以這兩個領域都有大量同類型產品。我大量讀庫,實力蒸蒸日上。創新院大裁人,我避風到SDO作盛大通行證,我深切地體會到現行開發模式的掣肘之處。我在創新院還能夠用前端模板搞定渲染問題,但這是一對一的。盛大通行證一個邏輯面向不一樣的視圖,要求務業邏輯與DOM渲染邏輯完全分離,要不無法進行下去。當時我只有求助於JAVA的設計模式,各類解耦。像後端spring,早已想到這一點,所以纔有IoC容器這樣的東西出來。在處理渲染方面,它們有龐大的標籤庫,這是面向組件開發的拓路者。爲了更好的控制標籤的行爲,微軟從MVC的基礎上發展起MVVM。MVVM用盡了23種設計模式,讓咱們輕鬆地操做一個叫VM的特殊數據源就能自動同步視圖,這種機制被稱之爲綁定。綁定在微軟的體系中分爲三種one way, one time, two way。微軟出身的Steve Sanderson搞出了第一個前端MVVM框架knockout。當時,09年,別說MVVM,MVC在前端也是新事物。前端MVC的風頭從jQueryMVC轉到backbone。個人注意力也停留在backbone身上。backbone有着後端JAVA MVC框架的優缺點,分類極細,責任明晰,但這也意味着繁鎖,定義了許多類,但好像又什麼也沒幹。其中這當中的類能夠由框架自動生成。jquery

模塊加載器開發了十多個版本號, 我着手開發UI庫了。這時愈感JQ的不便。UI是一種界面,很早之前人們就發現,幹這活是聲明式語言的強項。咱們平時熟悉的javascript, C, C++, java則擅長作邏輯。因而纔有前端模板這東西,將數據源往模板一套,界面就出來的。但以前的模板都屬於字符串模板,沒法對生成的元素節點進行後繼操做。不過,據元素節點的innerHTML的能耐來看,它也不執行裏面的script腳本。jquery的html能夠打破這桎梏,其實也基於eval處理的。最終,knockout仍是走入個人視野。很大一個緣由是我一直活躍於博客園,博客園屬於微軟系,微軟這個東西雖然難用一點,但在當時也算是至寶!git

knockout是一個偉大的框架,一直很低調。做者是後端的人,很JS用得爐火純青,大量的閉包,加之方法名,變量名是找C#那一套,名字巨長,搞得很難讀懂它的源碼。knockout的思想很簡單,把用戶的操做分紅兩部分,賦值與取值。賦值時,它就想辦法同步視圖。取值時,它就試圖取得各類操做的依賴關係。有了依賴關係,就能夠構成觀察者模式,讓視圖同步成爲可能。爲了達到這目的,必須讓框架知道當前進行的是什麼操做,操做的做用方是誰。因爲當時javascript訪問器屬性還不爲人知,在舊式IE也有兼容難題。knockout取採的策略是將全部屬性都轉換爲函數,根據函數有沒有傳參就能夠辨識用戶的行爲了。對於數組,它是重寫全部原生方法。avalon0.1-0.3就是追隨knockout的步伐,逐漸瞭解它的其餘概念與實現原理。好比說計算屬性,取值屬性,視圖刷新函數,各類經常使用的綁定。github

我以前談如何寫框架,就提到三個原則:複雜即錯誤,數據結構優於算法,出奇制勝。knockout的源碼太複雜,致使想參與的人蔘與不進來。爲了下降上手難度,你不管是從接口到實現,必定要條理清晰,不能處處是黑魔法與飛線方案。雖然avalon的源碼只有一個文件,裏面的條理是很是清晰的,而且刻意使用一些特殊的註釋來隔開各個功能區。API儘量少,許多重要的接口都不暴露出來,之後就能夠隨意折騰,不影響用戶使用了。在釐清knockout的實現機理後,我就是由單純的作輪子,轉爲發明新輪子。首先,屬性轉換爲函數這一用法必須去掉,太扭曲了。ember的作法是使用兩個上帝set, get方法來接管一切取值賦值操做,比knouckout好多了,但依然不直觀。angular是直接對控制器等函數取toString進行編譯,用法簡單了,但實現難度很是高,加之它其他設計把這易用性泯滅了。因而我轉來轉去,仍是求助於訪問器屬性解決了。這過程不是三言兩語說得清的,但從結果來看,就是Object.defineProperties與VBScript類的Set, Get, Let語法。用戶傳入一個對象,而後我轉出另外一個跟它很是類似,好像只是添加了幾個屬性的對象,而後用戶對它的屬性進行操做,它就能同步視圖,至關fantasy、 magic!易用性爆表了!

其次是綁定屬性的設計, knockout是使用data-bind對應一個沒有兩端花括號的JSON對象字符串,看似規整劃一,但這意味着內部要實現一個parser來轉換。後起之秀的angular則友好多了,但最終我是參照了rivetsjs。原因它的綁定風格能提供更多信息,更易分解,用戶也很易理解。這樣我就不用耗時實現一個龐大易出錯的parser了。編碼不一樣於建築,BUG與規模是成比例增加,控制代碼量是avalon在編寫過程的一個重要指標,至少它尚未超過4000行。

最後根據用戶的反饋,不斷增長新功能,在增長新功能時不斷引入BUG,而後修BUG,改好了,發現性能降低,因而提升性能。性能提升了,用戶又提出新功能,而後……周而復始,不斷與需求與BUG做鬥爭。這就像一個普通的產品的開發流程。不一樣的是,這個產品徹底是屬性於你,你有殺生大權,你能徹底享受用戶對你的讚譽。但反過來,其實我仍是得感謝那些敢吃螃蟹的人,那些提BUG的人,那些pull request的人。正由於,這項目比mass Framework發展得順利多了。它與最初的初版幾乎沒有一行相同的代碼,儘管我儘可能避免API的改動,API最後也有改動了,變得更加精巧。

0.4-0.7是脫胎換骨時期,它一直留在mass Framework項目的內部。0.72獨立出來,能夠獨擋一面了。這時不斷改進綁定的實現,一直到0.94才穩定下來。難點在於ms-each, ms-repeat, ms-with, ms-widget(ms-ui), ms-if這五種API。它們的特色都是有節點插入操做。有的是插入了移除,移除了插入, 有的是循環生成一堆相同節點,有的是按照一個模板生成一個控件。因爲綁定都有生命週期的概念,它的實現方式直接與它是否在DOM樹掛鉤,但如何是框架本身臨時移出DOM樹呢,因而就引起一系列問題了。幸虧最終都解決了。這基本是靠時間磨出來的,今天想不出來,睡一覺明天就想通一點點,後天又解決一點點……

facebook實現一個react的MVVM框架,炒做一個叫反應式編程的概念。其實它的核心就是knockout的弱化版。對我看來,用數學的自變量,因變量來表達它們之間的關係更適合。其中綁定屬性,監控數組的方法就是自變量,這是由用戶直接操做的。計算屬性,求值函數,視圖刷新函數就是因變量,由下層的綁定屬性,數組方法所驅動。0.99起,開始大量性能優化,把求值函數,視圖刷新函數都共享了。但這些東西,用戶根本不須要知道,說不定某天發現更高效的實現方式,它們就不存在了。全部要注意之處,在《入門教程》已經標明。要深刻能夠看《最佳實踐》。再者看源碼,這些概念只是輔助你看當前版本的源碼。想成爲高手,仍是從源碼着手。只是想快速完成任務,看個人《入門教程》就夠了。

感謝這個時代,正由於有了IE6纔有咱們前端,正由於有前端纔有咱們這些民科外行沾光IT的福利。

迷你MVVM框架在github的倉庫https://github.com/RubyLouvre/avalon

官網地址http://rubylouvre.github.io/mvvm/

有關avalon的最佳實踐或注意點請看這裏, 這個我每次發佈新版本均可能在這裏加東西


1.0的相關改進

  • 優化executeBindings, 插值表達式形式的文本綁定不須要removeAttribute
  • 優化scanText, 它生成的綁定屬性不須要element元素
  • fix duplex 綁定, 從左到右檢測匹配的vmodel
  • duplex 綁定添加表單檢證的鉤子
  • 優化監控數組的sort, reverse方法
  • avalon.fn.css支持設置多個屬性,優化舊式IE下的取寬高
  • 重構ms-widget, 過濾中間生成的VM, 支持在配置對象裏指定ID
  • 重構fixEvent
  • fix ms-class BUG
  • 優化nextTick
  • 爲性能考量,弱化avalon.Array.ensure
  • 移除data.remove屬性,經過是否存在求值函數evaluator來移除綁定屬性
  • 共享全部視圖刷新函數
  • clearChild 改名爲 clearHTML
  • IE67下添加getAttributes方法,直接使用正則抽取綁定屬性

朋友們用avalon作的東西

將來avalon的發展方向就是三大重型UI組件:樹,GRID,多級菜單。望你們也多多貢獻,一塊兒完善這個生態圈。

相關文章
相關標籤/搜索