利用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已經指明了它們的行為。因此當數據變動時,框架自然明白自己該什么做。

共{{array.size()}}條------------------合計{{total}}分

ID 姓名 分數 操作
{{el.id}} {{el.name}} {{el.score}} 移除

目前我與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已經在外國非常盛行,希望國人不要再落后太多了。


免責聲明!

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



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