<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div v-text="myText"></div>
</div>
<input type="text" v-model="myText">
</div>
<script src="likeVue.js"></script>
<script>
let vm=new Vue({
el:'#app',
data:{
myText:'这是数据驱动'
}
})
</script>
</body>
</html>
class Vue {
constructor(setting){
this.$el=document.querySelector(setting.el);
this.$data=setting.data;
//创建容器保存订阅者信息
this._directive={},this.newObj={};
this.Observer(this.$data);
this.Complie(this.$el);
}
//解析指令
Complie(el){
let nodes =el.children;
for(let i=0;i<nodes.length;i++){
let node =nodes[i]
if(node.hasAttribute('v-text')){
let attrval=node.getAttribute('v-text');
//push ??订阅者
this._directive[attrval].push(new Watcher(node,this,attrval,'innerHTML'));
}
if(node.hasAttribute('v-model')){
let attrval=node.getAttribute('v-model');
//push ??订阅者
this._directive[attrval].push(new Watcher(node,this,attrval,'value'));
//dom变化更新数据
node.addEventListener('input',()=>{
this.$data[attrval]=node.value;
this.newObj[attrval]=node.value;
// this._directive[attrval].forEach(item=>{
// item.update()
// });
})
}
if(node.children.length){
this.Complie(node)
}
}
}
//劫持数据
Observer(data){
for (let key in data) {
this._directive[key]=[];
// let val =data[key];
// let watcher =this._directive[key];
// Object.defineProperty(this.$data,key,{
// get:function(){
// return val;
// },
// set:function(newVal){
// if(newVal!==val){
// val =newVal;
// watcher.forEach(item=>{
// item.update()
// })
//
// }
// }
// })
}
let self=this;
this.newObj = new Proxy(data, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
self._directive[key].forEach(item=>{
item.update();
})
return Reflect.set(target, key, value, receiver);
},
});
}
}
//订阅者-->负责自己更新本身状态
class Watcher{
constructor(el,vm,exp,attr){
this.el=el;
this.vm=vm;
this.exp=exp;
this.attr=attr;
this.update();
}
update(){
this.el[this.attr]=this.vm.$data[this.exp]
}
}