本版本最大的改進是啟用全新的parser。
parser是用於干什么的?在視圖中,我們通過綁定屬性實現雙向綁定,比如ms-text="firstName", ms-html="sex + '士'", ms-visible="Math.abs(toggle + 2000) >= 20", 我們需要將它們轉換為求值函數。我們通過ms-controller="vm"來綁定ViewModel,比如vm = { firstName: '司徒'}, 那么對於上面的第一個綁定,我們想讓它變成函數,以前是這樣實現的:
function anonymous(vm1372575919386) { with (vm1372575919386) { var ret1372575919386 = firstName } return ret1372575919386 }
然后視圖刷新函數會將vm傳入此函數,var ret = anonymous(vm), 得到'司徒',然后node.value = ret(注,這里的node 為文本節點,它在掃描DOM樹時被抽取出來),完成視圖的最少化刷新。這個過程中如何將綁定屬性的值轉換為求值函數顯然是重中之重。
之前的parser,正如大家看到的那樣,非常簡單,然后with表達式一包,然后返回結果。但with在ES5的嚴格模式下運行不了,也一直為性能潔癖人士所不齒。並且它存在一個問題,它的依賴收集並不完整。比如下面這種
aaa {{test1 && test2}}
上面的插值表達式是一個文本綁定,轉換為求值函數時,為:
function anonymous(vm1372575919386) { with (vm1372575919386) { var ret1372575919386 = test1 && test2 } return ret1372575919386 }
當一開始test1為false, test2為true時,由於短路與的關系,我們並沒有對test2進行取值。由於avalon只在求值函數的第一次執行時收集依賴,在依賴是通過求值賦值語句實現的,而這時,我們就肯定遺漏了test2了。因此一個全新的parser就迫在眉睫了。
新的parser的實現思路時,設法抽取到綁定值中的變量,然后轉換為賦值語句,放到求值函數的最前面,這樣就不會遺漏任何依賴了。問題是如何得到這些變量。比如上面三例,它們的變量依次是firstName, sex, toggle,我們要設法去掉所有雜質,首先要去掉注釋,字符串,正則這些字面量,然后是加減乘除這些操作符,然后是if, while, for, undefined, void 等關鍵字,然后是作為某個對象的屬性或方法存在的語句,如.prop,然后逗號這樣用於斷句用的符號。但即使這樣,還會留下像Math, String等全局變量,這時我們就通過vm取hasOwnerProperty進行排除。
下面就是通過新的parser轉換得到的求值函數。
function anonymous(vm1372575919386) { var firstName = vm1372575919386.firstName return firstName } function anonymous(vm1372575919386) { var test1= vm1372575919386.test1, test2 = vm1372575919386.test2 return test1 && test2 }
並且進一步,我們可以在里面塞進'use strict'來提高性能。
function anonymous(vm1372575919386) { 'use strict'; var firstName = vm1372575919386.firstName return firstName } function anonymous(vm1372575919386) { 'use strict'; var test1= vm1372575919386.test1, test2 = vm1372575919386.test2 return test1 && test2 }
如何存在過濾器
{{ new Date | date('dd MM yyyy') }}
function anonymous(vm1372896828095_0, filters1372896828095) { 'use strict'; var ret1372896828095 = new Date if (filters1372896828095.date) { try { ret1372896828095 = filters1372896828095.date(ret1372896828095, 'dd MM yyyy') } catch (e) { } } return ret1372896828095 }
憑借着此新parser,avalon又有了一個質的提高。有關的parser的實現,可以詳看該issue
讀者們也可以對比angular的parser實現, avalon的是非常小巧的。
迷你MVVM框架在github的倉庫https://github.com/RubyLouvre/avalon
官網地址http://rubylouvre.github.io/mvvm/
大家可以加入QQ群:79641290進行討論,此群為技術群,禁水!