avalonJS-源码阅读(二)
上一篇文章讲述的avalon刷页面所用到的几个函数。这篇则是主要讲avalon对刷DOM刷出来的avalon自定义属性如何处理的。 目录[-] avalon页面处理(2) 数据结构 解析avalon标签 parseExpr parseExprProxy 函数介绍 createCache 小结 附录 测试demo avalon页面处理(2) 上一篇文章讲述的avalon刷页面所用到的几个函数。这篇则是主要讲avalon对刷DOM刷出来的avalon自定义属性如何处理的。 数据结构 看js代码最头疼的就是数据流转时的数据结构变化。 //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 } 解析avalon标签 有了数据结构后,看源码就稍微轻松些了。解析标签的功能主要存在bindingHandlers对象内。bindingHandler主要是对avalon标签进行分类和按实际情况进行处理,就像做javascript UI 插件一样。他所用到两个很重要的函数分别是parseExprProxy和parseExpr。 parseExpr parseExpr的主要作用是根据ms-what、{{what}}、vmodule和先前定义的filters等生成Function,并存储在evaluator下(参看bindingHandlers data数据结构)。下面是各种生成后的 function整理。 //简单的绑定个属性 例如 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 parseExprProxy主要作用是通过调用parseExpr 生成function,然后进行相应的dom订阅。它还帮助parseExpr处理了类似ms-href='http://{{abc}}ff{{abd}}'的分支。至于如何dom订阅, 不属于本篇的范畴。 函数介绍 createCache createCache:创建固定大小缓存,直接拿来收藏好了。 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 插件一样,没多大激情(当然,写的话就费 劲了),所以就不去细细讲述了。 附录 测试demo <!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>