利用avalon 實現一個簡單的成績單

利用avalon 實現一個簡單的成績單

本文的靈感是來自Halower的這篇博文,他是使用knockout與jQuery實現的。不過我覺得MVVM本來就強大的事件綁定功能,因此用jQuery 是多此一舉。另,他也用了一些面向對象的寫法。我個人認爲,純數據就該好好當純數據,作爲數據模型(M)而存在,想操作數據,則交由視圖模型(VM)。在angularjs流行的一些成規,都是要求大家不要自己操作DOM,DOM是框架自行幫你偷偷搞定。這也與avalon一直提倡的“操作數據即操作DOM”的理念相符。由於avalon巧妙地利用了Object.defineProperty, __defineSetter__, __defineGetter__, VBScript等方法把等於號(=)重載了,因此與視圖的同步就變得比其他MVVM更隱祕神奇。那麼接着下來,讓我們看看avalon是如何實現這個功能吧。

首先是視圖層,裏面的綁定屬性其實可以在VM中的屬性定了下來再添加。這也涉及MVVM另一個優勢,分離關注點,因此切圖與JS編程可以同時進行。由於JS代碼不進行DOM操作,頁面長得怎麼樣也無所謂,我又不需要選擇器引擎!

<div ms-controller="grid" class="grid" >
    <div>
        <p> <input ms-duplex="id">
            <input ms-duplex="name">
            <input ms-duplex="score" data-duplex-event="change"></p>
        <p><button ms-click="add"> add</button></p>
    </div>
    <p>共{{array.size()}}條------------------合計{{total}}分</p>
    <table>
        <thead>
            <tr>
                <th>ID</th> <th>姓名</th> <th>分數</th> <th>操作</th>
            </tr>
        </thead>
       
        <tbody ms-each-el="array">
            <tr>
                <td>{{el.id}}</td>
                <td>{{el.name}}</td>
                <td>{{el.score}}</td>
                <td align="center"><a ms-click="$remove" href="javascript:void(0)">移除</a></td>
            </tr>
        </tbody>
    </table>
    <textarea ms-value="JSON.stringify(array.$model)" style="width:90%;height:220px;"></textarea>
</div>

樣式隨便弄弄:

.grid table{
    border:1px solid #000;
    width:500px;
    border-collapse: collapse;
}
.grid button{
    width:400px;
    background: orange;
}
.grid table th, .grid table td{
    border:1px solid #000;
    padding: 2px 5px;
}

從HTML結構來看,分爲兩部分,一個是用於輸入數據,另一個是呈現所有數據,數據上方還有個小統計。輸入數據部分有三個輸入項,我們對分數中進行校驗,只保證其是數字就行了,目的是爲了相加,因爲input的value屬性總爲一個字符串類型。下方有個按鈕,用於提交。呈現區爲一個table,所有MVVM框架都支持數組循環輸出,我的與angular走得很近。在循環區域,裏面還內置一個$remove方法,用於刪除監控數組中的某一個元素,這個比knockout人性化多了。下面是JS部分,你是看不到一句操作DOM的代碼。

//如果大家對avalon不熟悉,可以參看這篇入門教程 http://www.cnblogs.com/rubylouvre/p/3181291.html
            avalon.ready(function() {
                var model = avalon.define('grid', function(vm) {
                    vm.id = ""
                    vm.name = ""
                    vm.score = 0
                    vm.total = 0
 
                    vm.add = function() {
                       if(vm.id && vm.name ){
                           vm.array.push({
                              id: vm.id,
                              name: vm.name,
                              score: vm.score
                           })
                       }
                    }
                    vm.array = []          
               });
 
                model.$watch("score", function(a) {
                        var a = Number(a) || 0
                        a = a > 100 ?  100 : a < 0 ? 0 : a//強制轉換爲0~100間
                        model.score = a
                })
                model.array.$watch("length", function() {
                    var a = 0
                    model.array.forEach(function(el) {
                        a += el.score//求得總數
                    })
                    model.total = a;
                    model.id = ""
                    model.name = ""
                    model.score = 0
                })
                model.array = [
                    {id: "d1", name: "李世民", score: 67},
                    {id: "d2", name: "贏政", score: 90}
                ]
 
                avalon.scan();
            });

我們在define方法中定義了VM所有用到的數據,什麼id, name, score, array, 還有需要綁到視圖中的add方法。數據校驗或數據變動時需要做的操作,我們是用$watch實現,它們被安排到define方法外,這是一個好主意。然後,就沒有然後了!這就是MVVM的神奇之處,因爲我們在視圖中使用了{{}}, ms-click已經指明瞭它們的行爲。因此當數據變動時,框架自然明白自己該什麼做。

  

共2條------------------合計157分

ID 姓名 分數 操作
d1 李世民 67 移除
d2 贏政 90 移除

目前我與5羣的一些人已經將avalon應用於公司的生產環境,反應還是不錯。雖然目前還不時冒出一些怪異的BUG,但難度不至於影響我們的進度,基本上半天就能修,比如說IE9-10的option標籤的value問題,firefox 全系列下,未插入DOM樹的元素的display樣式取值問題,這是jQuery也沒報到的新東西。有的話,我在做mass Framework時已經遇到過了。MVVM是一個全新的領域,要求對用戶全面隱藏DOM操作,並將整個DOM樹作爲一個動態模板或數個複用的子模板,另外,DOM樹其實也被我框架看作爲一個Ioc容器的配置文件。如此種種,遭遇新的問題在所難免,但只要方向是對的,這就是康莊大道。雖然它與jQuery走的是一條截然不同的路,但明顯優於jQuery。jQuery與DOM存在強依賴,導致維護成本奇高。這正是西方繼jQuery後,又孜孜不倦發明backbone, canjs, knockout, emberjs, angular的原因。現在國內的技術步伐普通比外國慢兩三年,現在前端MVVM已經在外國非常盛行,希望國人不要再落後太多了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章