MVVM(Model-View-ViewModel)是在MVC(Model-View-Control)形式以後引出的新的開闢形式,他與MVC
形式一樣用於把視圖(界面)和數據舉行解耦,差別的是採納ViewModel來完成數據與視圖的雙向綁定,通
過自動化的體式格局負擔大部分數據事情,來處理因為界面複雜化和疾速迭代帶來的題目。
因為如今vue比較火,如今就用vue雷同的道理(屬性挾制)來完成一個簡樸MVVM框架
建立dom
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綁定的數據都在這兒
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時都邑觸發自定義事宜,完成對視圖的跟新。
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框架。
View.init('#app');