上一篇文章講述的avalon刷頁面所用到的幾個函數。這篇則是主要講avalon對刷DOM刷出來的avalon自定義屬性如何處理的。javascript
看js代碼最頭疼的就是數據流轉時的數據結構變化。html
//attr bindings //例如 <div ms-dbclick-_abc='func'></div> { type:$string,//也就是ms-...後面的信息,例如 ms-duplex 則爲 type:duplex,注意,遊覽器事件(event)如click,mousemove等統一爲type:on param:$string//"_abc" element:$node//當前節點 name:$string//ms-dbclick-_abc value:$string//func priority:$Num//優先級。 //"if": 10, //"repeat": 90, //"widget": 110, //"each": 1400, //"with": 1500, //"duplex": 2000, //"on": 3000 //值越大優先級越高 } //text bindings 從上一篇拉過來 { type: "text|html",//類型 node: node,//替換後的element nodeType: 3,//節點類型 value: token.value, filters: token.filters replaceNodes:$array//[node] //token 爲scanExpr的返回值 } //text token { value:$string//具體值 expr:$boolean//是否是在{{...}}內 filters:$array|void 0 //過濾器 } //bindingHandlers data { handlerName:$name//被bindingHandlers中哪一個方法執行了解析。因爲href src等都經過attr來處理,因此經過bindings 的type屬性不可靠 evaluator:$func//由parseExpr 生成的函數。 ...//上面 的text bindings 和attr bindings }
有了數據結構後,看源碼就稍微輕鬆些了。解析標籤的功能主要存在bindingHandlers
對象內。bindingHandler
主要是對avalon標籤進行分類和按實際狀況進行處理,就像作javascript UI插件同樣。他所用到兩個很重要的函數分別是parseExprProxy
和parseExpr
。java
parseExpr
的主要做用是根據ms-what
、{{what}}
、vmodule和先前定義的filters等生成Function,並存儲在evaluator下(參看bindingHandlers data數據結構)。下面是各類生成後的function整理。node
//簡單的綁定個屬性 例如 ms-href={{name}} function anonymous(vm1399087422863_0/**/) { 'use strict'; var name = vm1399087422863_0.name return name; } //帶有filter的,例如 {{name | uppercase}} function anonymous(vm1399088892713_0,filters1399088892713/**/) {//filters1399088892713 會將全部現有filters做爲key/value傳遞進來 'use strict'; var name = vm1399088892713_0.name var ret1399088892713 = name if(filters1399088892713.uppercase){ try{ ret1399088892713 = filters1399088892713.uppercase(ret1399088892713) }catch(e){} } return ret1399088892713 } //ms-duplex='name' function anonymous(vm1399091173121_0/**/) { 'use strict'; return function(vvv){ var name = vm1399091173121_0.name; if(!arguments.length){ return name } vm1399091173121_0.name= vvv; } } //ms-on ms-click="click" function anonymous(vm1399093434491_0/**/) { 'use strict'; var click = vm1399093434491_0.click if(avalon.openComputedCollect) return ; return click; }
上面是三個分支(第一個function和第二個function屬於同一分支)最基本的例子,複雜一些的也基本是以此作基礎衍生出來的,本身能夠嘗試着看着以上代碼寫一些複雜點的function出來,並和avalon生成的作對比。parseExpr在生成function的時候會涉及緩存生成函數和緩存函數的uniId生成。
緩存的源碼和測試demo會在後面寫上。緩存
parseExprProxy主要做用是經過調用parseExpr 生成function,而後進行相應的dom訂閱。它還幫助parseExpr
處理了相似ms-href='http://{{abc}}ff{{abd}}'
的分支。至於如何dom訂閱,不屬於本篇的範疇。數據結構
createCache
:建立固定大小緩存,直接拿來收藏好了。dom
function createCache(maxLength) { var keys = [] function cache(key, value) { if (keys.push(key) > maxLength) { delete cache[keys.shift()] } return cache[key] = value; } return cache; } var c= createCache(256); //c("key","value")//value //c("key")//value
這篇篇幅較短,avalon關於DOM處理 ms-, {{...}}
核心除了parseExpr
函數外,還有bindingHandlers
對象,而看這個代碼真如看javascript UI 插件同樣,沒多大激情(固然,寫的話就費勁了),因此就不去細細講述了。函數
<!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="avalon.js"></script> </head> <body> <div ms-controller="nihao"> <a ms-href='{{name}}'>abc</a> {{name|uppercase}} <input type='text' ms-duplex='name'/> <button ms-click='click'>button</button> <a ms-href='http://abc/{{name}}'>test parseExprProxy</a> </div> <script> avalon.define("nihao", function(vm) { vm.name='nihao' vm.cla=true vm.click=function(){ console.log("click!"); return } }) </script> </body> </html>