概述
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>
</style>
</head>
<body>
<div id='app'>
<input type="text" v-model="hello"/>
{{hello}}
<div>
<div>{{name}}</div>
</div>
</div>
<script>
//发布者
function Dep(){
this.subs=[]
}
Dep.prototype.addSub = function(_watcher){
this.subs.push(_watcher);
}
Dep.prototype.upDate = function(){
// console.log(this.subs)
this.subs.map(_watcher=>{
console.log(_watcher)
_watcher.upDate();
})
}
//订阅者
function watcher(vm,node,name){
Dep.target = this;
this.vm=vm;
this.node=node;
this.name=name;
this.upDate();
Dep.target=null;
}
watcher.prototype.upDate=function(){
console.log('被调用啦???')
this.node.nodeValue=this.vm[this.name];
}
function MVVM(opt){
this.id = opt.el;
this.data = opt.data;
this.observe(this.data,this)
this.dom = this.nodeToFragment(document.getElementById(this.id),this);
document.getElementById(this.id).append(this.dom);
}
MVVM.prototype.nodeToFragment = function(dom,vm){
//把#app下的全部保存到文档碎片中
var frag = document.createDocumentFragment();
var child;
while(child = dom.firstChild){
var _child = this.complie(child,vm)
frag.append(_child);
}
return frag;
}
MVVM.prototype.complie = function(dom,vm){
// 这里主要是把#app 下的dom节点全部解析
var reg = /{{(.*)}}/;
switch(dom.nodeType){
case 1://dom节点;
var atte = dom.attributes;
for(var i=0;i<atte.length;i++){
if(atte[i].nodeName == "v-model"){
var name = atte[i].nodeValue;
dom.addEventListener('input',function(e){
vm[name]=e.target.value;
})
dom.value = vm[name];
dom.removeAttribute("v-model");
}
}
dom.append(this.nodeToFragment(dom,vm));
break;
case 3://文本节点
var value = dom.nodeValue;
if(reg.test(value)){
var name = RegExp.$1;
name = name.trim();
new watcher(vm,dom,name);//对每个文本节点,当做是一个订阅者
}
break;
}
return dom;
}
MVVM.prototype.observe = function(obj,vm){
//将data下的数据全部进行get set监听,然后放置到根对象下
Object.keys(obj).map( key =>{
this.defineProperty(vm,key,obj[key])
})
}
MVVM.prototype.defineProperty=function(obj,key,val){
var dep = new Dep();
Object.defineProperty(obj,key,{
get:function(){
//把该字段当做发布者
//把调用该字段的dom节点当做订阅者
if(Dep.target) dep.addSub(Dep.target);
console.log('需要取数据',key,'<>',val)
return val;
},
set:function(newVal){
if(val !== newVal){
console.log('需要更新数据',val,"--->",newVal)
val=newVal;
dep.upDate();
//发布者进行全局更新
}
}
})
}
var vue = new MVVM({
el:'app',
data:{
hello:'hello world',
name:'小明'
}
})
</script>
</body>
</html>
最后
以上就是还单身口红为你收集整理的MVVM双向绑定简单实现的全部内容,希望文章能够帮你解决MVVM双向绑定简单实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复