迷你MVVM框架 avalonjs 學習教程21、雙向綁定鏈


avalon的雙向綁定機制,是通過一條依賴鏈實現。此依賴鏈最底層是監控屬性、監控數組,中層是計算屬性、監控函數,再上點是求值函數,最上層是視圖刷新函數。

enter image description here

所謂計算屬性,監控屬性,監控函數屬性,我們改變它們的值,它們會引發視圖變化;而監控數組,是我們調用它的一些方法,也會引發視圖變化。

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>

enter image description here

<!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>

enter image description here 一般情況下,都是上層依賴下層,下層發生改變,就會自動向上冒泡,到視圖刷新函數這一層,實現視圖的改變,只有一個例外,就是ms-duplex。它會偷偷 在視圖上綁定一些事件,通過監聽表單元素的值,將它直接同步到下方的監控屬性與計算屬性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM