vue中的v-model可以实现双向绑定,其核心思想通过Object.definePropery来对Vue的数据进行数据劫持,
主要分为三部分
observer主要是负责对Vue数据进行数据劫持,使其数据拥有get和set方法
需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
指令解析器负责绑定数据和指令,绑定视图更新方法
compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
watcher负责数据监听,当数据发生改变通知订阅者,调用视图更新函数更新视图
Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
用一张图来简单了解一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2 id="h2"></h2>
<div id="app">
<input v-model="name" type="text" placeholder="姓名">
<input v-model="age" type="text" placeholder="年龄">
<input v-model="address" type="text" placeholder="地址">
<input v-model="phoneNumber" type="text" placeholder="电话号码">
<div>
<ul>
<li>姓名: {{name}}</li>
<li>年龄: {{age}}</li>
<li>地址: {{address}}</li>
<li>
<p>
电话号码: {{phoneNumber}}
</p>
</li>
</ul>
</div>
</div>
</body>
<script>
/* function MVVM(opations) {
}*/
class MVVM{
constructor(opations){
this.el = opations.el;
this._data = opations.data;
this.init()
}
init(){
//数据代理
this.initData();
// this.initDOM();
}
initData(){
// this == vm
let me = this;
for(let key in me._data){ //key == name
if(!me._data.hasOwnProperty(key)) return;
Object.defineProperty(me, key, { //key == name
configurable: false,
enumerable: true,
get(){
return me._data[key]
},
set(newValue){
me._data[key] = newValue;
}
})
}
}
}
//MVVM.prototype.xxx
/*
* 1.数据代理 -->响应式数据 Object.defineProperty
* 2.input - 绑定事件keyup -> 事件处理相关函数 -> 改变数据
* 3.获得相关的DOM元素 -> 数据 <=> 相应的DOM发生改变
*
* */
</script>
<script>
let vm = new MVVM({
el:"app",
data:{
name:"哈哈",
age:"",
address: "",
phoneNumber: ""
}
})
console.log(vm.name, vm)
vm.age = 18
</script>
</html>