<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="vmDom">
<input type="text" name="" v-model="name" placeholder="请输入姓名">
姓名是:<label v-text="name"></label>
<div>
<input type="text" name="" v-model="age" placeholder="请输入年龄">
年龄是:<label v-text="age"></label>
</div>
</div>
</body>
<script>
class MVVM{
constructor(options){
this.options = options;
this.$data = options.data;
this.$el = document.querySelector(options.el);
//ES6 Proxy用法
this.$proxy = {};
//订阅者存放容器 采用{指令1:[],指令2:[]}的格式 按指令进行分类,不干扰不相干指令,也就是个别渲染而非全部渲染
this._directive = {};
this.Observer(this.$data);
this.Compile(this.$el);
}
//劫持数据
Observer(data){
// ES5用法
// for(let key in data){
// this._directive[key] = [];
// let val = data[key];
// let wachers = this._directive[key];
// Object.defineProperty(this.$data,key,{
// get(){
// return val;
// },
// set(newVal){
// if(newVal == val){
// val = newVal;
// return;
// }
// val = newVal;
// wachers.forEach(w =>{
// w.update();
// });
// }
// })
// }
//ES6 Proxy用法
for(let key in data){
this._directive[key] = [];
}
const self = this;
this.$proxy = new Proxy(this.$data,{
set(target,property,newVal){
if(target[property] === newVal){
return;
}
target[property] = newVal;
let wachers = self._directive[property];
wachers.forEach(w =>{
w.update();
});
return true;
}
});
}
//解析指令
Compile(el){
for(let i=0;i<el.children.length;i++){
let item = el.children[i];
if(item.children.length > 0){
this.Compile(item);
}
if(item.hasAttribute("v-text")){
let attrVal = item.getAttribute("v-text");
// ES5用法
// this._directive[attrVal].push(new Wacher(item,"innerText",this.$data,attrVal));
this._directive[attrVal].push(new Wacher(item,"innerText",this.$proxy,attrVal));
}
if(item.hasAttribute("v-model")){
let attrVal = item.getAttribute("v-model");
// ES5用法
// this._directive[attrVal].push(new Wacher(item,"value",this.$data,attrVal));
this._directive[attrVal].push(new Wacher(item,"value",this.$proxy,attrVal));
item.addEventListener('input', e => {
// ES5用法
// this.$data[attrVal] = item.value;
this.$proxy[attrVal] = item.value;
});
}
}
}
}
//订阅者
class Wacher{
constructor(el,attr,vm,key){
this.el = el;
this.attr = attr;
this.vm = vm;
this.key = key;
this.update();
}
update(){
this.el[this.attr] = this.vm[this.key];
}
}
const vm = new MVVM({
el:'#vmDom',
data:{
name:'kerry',
age:28
}
});
</script>
</html>
网友评论