對MVVM架構的一些理解

MVVM(Model-View-ViewModel)是在MVC(Model-View-Control)模式以後引出的新的開發模式,他與MVC
模式同樣用於把視圖(界面)和數據進行解耦,不一樣的是採用ViewModel來完成數據與視圖的雙向綁定,通
過自動化的方式承擔大部分數據工做,來解決因爲界面複雜化和快速迭代帶來的問題。html

因爲如今vue比較火,如今就用vue相同的原理(屬性劫持)來完成一個簡單MVVM框架vue

建立domnode

var html="<input type="text" v-model="msg">{{msg}}<p>{{msg2}}</p><p>{{msg}}</p>";
var div = document.createElement('div');
div.id='app';
div.innerHTML = html;
document.body.appendChild(div);

數據對象(Model),與dom綁定的數據都在這兒app

var Model = {
    msg:'hello world',
    msg2:'hello world2'
};

視圖對象(View),裏面封裝了對dom節點的解析、事件綁定、視圖更新渲染等方法框架

var View = {
    init:function(el){
        //將數據與View綁定
        ViewModel.bind(Model);
        //解析Dom
        this.processNode(el);
    },
    subs:[],
    processNode:function(el){
        var node = document.querySelector(el);
        var frag = document.createDocumentFragment(),child;
        while(child = node.firstChild){
            this.compile(child);
            frag.appendChild(child);
        }
        node.appendChild(frag);
    },
    compile:function(node){
        function Sub(node,name,nodeType){
            this.node = node;
            this.name = name;
            this.nodeType = nodeType;
        }
        var self = this;
        if(node.nodeType === 1){
            if(node.childNodes){
                var nodes =[...node.childNodes];
                nodes.forEach(function(node){
                    self.compile(node);
                })
            }
            var attrs = [...node.attributes];
            attrs.forEach(function(attr){
                if(attr.nodeName === 'v-model'){
                    var name = attr.nodeValue;
                    node.addEventListener('input',function(e){
                        self[name] = e.target.value;
                    });
                    node.value = self[name];
                    node.removeAttribute('v-model');
                    var sub = new Sub(node,name,'input');
                    self.render(sub);
                    self.subs.push(sub);
                }
            })
        }
        if(node.nodeType === 3){
            if(/\{\{(.*)\}\}/.test(node.nodeValue)){
                var name = RegExp.$1;
                name=name.trim();
                var sub = new Sub(node,name,'text');
                self.render(sub);
                self.subs.push(sub);
            }
        }
    },
    update:function(){
        var self = this;
        this.subs.forEach(function(sub){
            self.render(sub);
        })
    },
    render:function(sub){
        if(sub.nodeType === 'input'){
            sub.node.value=this[sub.name];
        }
        if(sub.nodeType === 'text'){
            sub.node.nodeValue=this[sub.name];
        }
    }
};

視圖模板綁定對象(ViewModel),這也是mvvm實現的核心方法,經過defineProperty將Model對象中的數據
複製到了View對象中,並對數據進行了監控,每當get或set時都會觸發自定義事件,完成對視圖的跟新。dom

var ViewModel={
    bind:function(m){
        Object.keys(m).forEach(function(key){
            Object.defineProperty(View,key,{
                get:function(){
                    return m[key];
                },
                set:function(newVal){
                    m[key] = newVal;
                    this.update();
                }
            })
        });
    }
};

最後調用View對象的初始化方法執行框架,至此就完成了一個簡單的MVVM框架。mvvm

View.init('#app');
相關文章
相關標籤/搜索