avalon的雙向綁定機制,是通過一條依賴鏈實現。此依賴鏈最底層是監控屬性、監控數組,中層是計算屬性、監控函數,再上點是求值函數,最上層是視圖刷新函數。
所謂計算屬性,監控屬性,監控函數屬性,我們改變它們的值,它們會引發視圖變化;而監控數組,是我們調用它的一些方法,也會引發視圖變化。
var vm = avalon.define({ a: "這是監控屬性", $b: "這是非監控屬性", $skipArray: ["c", "d"], c: "位於$skipArray里,因此也是非監控屬性", d: "位於$skipArray里,因此也是非監控屬性", obj: {//這個obj是一個子VM xx: "xxx" }, fn: function() { alert(1)//這里面沒有vm的監控屬性(僅指其第一層屬性),因此是一個普通函數 }, fn2: function() { return vm.a //這里面有vm的監控屬性(僅指其第一層屬性),因此是一個監控函數 }, fn3: function() { return vm.fn2()//fn2是方法而不是監控屬性,因此也是一個普通函數 }, array: [1, 2, 3], //這是一個監控數組 computed: {//這是一個計算屬性,因此它有一個get方法,this指向vm get: function() { return this.a + this.$b } }, computed2: {//這是一個計算屬性,因此它有get,set方法 get: function() { return this.a + "!!!" }, set: function(v) { this.a = v } }, ccc: {//這一個普通的對象,構成一個子VM,因為計算屬性只允許最多有兩個方法,不能出現第三個屬性 get: function() { return this.a + "!!!" }, set: function(v) { this.a = v }, host: {} } })
為了性能起見,我們需要將一些屬性變成不可監控。這有兩個途徑,在屬性名或方法名前加一個$,或者把屬性名放到$skipArray數組里。
監控屬性,計算屬性,監控屬性什么都是位於VM中;而最上面兩層是位於視圖,通過分解綁定屬性,推斷出來。比如說ms-text=”aaa”,我們從屬性名得到其視圖刷新函數(所有視圖刷新函數都定義在 avalon.bindingExecutors對象上),求值函數是通過內部的parseExpr方法編譯出來。
<!DOCTYPE html> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width"> <script src="avalon.js" type="text/javascript"></script> <script> vmodel = avalon.define({ $id: "test", a: 1, b: 2, fn: function() { return (parseFloat(vmodel.a) || 0) + (parseFloat(vmodel.b) || 0) } }) </script> </head> <body ms-controller="test"> <div><input ms-duplex="a"/>{{a}}</div> <div><input ms-duplex="b"/>{{b}}</div> <div>{{fn()}}</div> </body> </html>
<!DOCTYPE html> <html> <head> <title>ms-class</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="avalon.js"></script> <style> .green{ background: green; } </style> <script type="text/javascript"> var model = avalon.define({ $id: "test", array: [], add: function(){ model.array.push(1) }, remove: function(){ model.array.pop() } }) </script> </head> <body ms-controller="test" > <div ms-class="green: array.length" style="width:400px;height:200px"> <button ms-click="add" type="button">add</button><button ms-click="remove" type="button">remove</button> </div> </body> </html>
一般情況下,都是上層依賴下層,下層發生改變,就會自動向上冒泡,到視圖刷新函數這一層,實現視圖的改變,只有一個例外,就是ms-duplex。它會偷偷 在視圖上綁定一些事件,通過監聽表單元素的值,將它直接同步到下方的監控屬性與計算屬性。