原理

vm 始终可以将 data 对象的数据 加工到 vm._data ,无论data对象中的元素有多少子对象
测试用例,运行可以在浏览器的控制台查看:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue监测数据改变的原理</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
address:'北京',
student:{
name:'tom',
age:{
rAge:40,
sAge:29,
},
friends:[
{name:'jerry',age:35}
]
}
}
})
</script>
</html>
模拟一个数据监测
源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script type="text/javascript" >
let data = {
name:'尚硅谷',
address:'北京',
}
//创建一个 监视的 实例对象,用于监视 data中属性 的变化
const obs = new Observer(data)
console.log(obs)
//准备一个vm实例对象
let vm = {}
vm._data = data = obs
//写一个监视函数:
function Observer(obj){
//汇总 obj对象中所有的属性名 形成一个 数组
const keys = Object.keys(obj)
//遍历 keys 数组中的 每个元素k, 然后为每个k增加 getter, setter
keys.forEach((k)=>{
//this - 是 Observer() 的实例对象
//通过 Object.defineProperty() 为 this对象中的k元素增加 getter setter
Object.defineProperty(this,k,{
get(){
//把传入的对象身上k对应的值传出去。
return obj[k]
},
set(val){
//$(k) 模板字符串
console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了\n`)
//把传入的对象身上k对应的值修改为 val
obj[k] = val
}
})
})
}
</script>
</body>
</html>上面源码中 k 的理解:
k 是 Object.keys(obj) 返回的数组中的每一个元素,也就是 obj 对象中每一个可枚举的自身属性名。
假设 obj = { name:'尚硅谷', address:'北京' }
const keys = Object.keys(obj)
// keys = ['name', 'address']
keys.forEach((k) => {
// 第一次循环:k = 'name'
// 第二次循环:k = 'address'
Object.defineProperty(this, k, {
get(){ return obj[k] },
set(val){ ... }
})
})
所以:
- 第一次循环:
k = 'name',为this对象添加name属性的 getter/setter - 第二次循环:
k = 'address',为this对象添加address属性的 getter/setter
