目标
-
模拟一个最小版本的 Vue
-
响应式原理在面试的常问问题
-
学习别人优秀的经验, 转换成自己的经验
-
实际项目中出问题的原理层面的解决
- 给 Vue 实例新增一个成员是否是响应式的?
- 给属性重新赋值成对象, 是否是响应式的?
-
为学习 Vue 源码做铺垫
数据驱动
- 数据响应式、双向绑定、 数据驱动
- 数据响应式
- 数据模型仅仅是普通的 JavaScript 对象,而当我们修改数据时,视图会进行更新。避免了繁琐的DOM 操作,提高了开发效率。
- 双向绑定
- 数据改变, 视图改变,视图改变, 数据也随之改变
- 我们可以使用 v-model 在表单元素上创建双向数据绑定
- 数据驱动是 Vue 最独特的特性之一
-
开发过程中仅需要关注数据本身, 不需要关心数据是如何渲染到视图
-
数据响应式的核心原理
Vue 2.x
-
浏览器兼容 IE8 以上(不兼容 IE8)
let data = {
msg: 'hello',
count:10
}
let vm = {}
// 数据劫持, 当访问或者设置 vm 中的成员的时候,做一些干预操作
Object.defineProperty(vm,'msg',{
// 可枚举 (可遍历)
enumerable: true,
// 可配置(可以使用 delete 删除,可以通过 defineProperty 重新定义)
configurabel: true,
get () {
console.log('get',data.msg)
return data.msg
},
set(newValue){
console.log('set', newValue)
if(newValue === data.msg) {
return
}
data.msg = newValue
document.querySelector("#app").textContent = data.msg
}
})
vm.msg = 'hello world'
console.log(vm.msg)
如果一个对象中有多个属性需要转换getter/setter 方法
通过 Object.key 遍历实现多个属性响应式方法。
总结: vue2.0 版本的响应式原理就是通过 object.defineProperty 的 get 和 set 方法实现的。
let data = {
msg: 'hello',
count: 10
}
let vm = {}
proxyData(data)
function proxyData(data) {
Object.keys(data).forEach(key => {
Object.defineProperty(vm, key, {
// 可枚举 (可遍历)
enumerable: true,
// 可配置(可以使用 delete 删除,可以通过 defineProperty 重新定义)
configurabel: true,
get(){
console.log('get: ',key, data[key])
return data[key]
},
set(newValue){
console.log('set:' , key, newValue)
if(newValue = data[key]){
return
}
data[key] = newValue
// 数据更改,更新 DOM 的值
document.querySelector("#app").textContent = 20
}
})
})
}
Vue3.0 响应式原理
- MDN-Proxy :用于创建一个对象的代理,从而实现基础操作的拦截和自定义(如属性查找,赋值,枚举,函数调用等)
- 直接监听对象而非属性
- ES6 新增 IE 不支持,性能由浏览器变化
- 总结: vue3.0 响应式原理, 主要是通过 proxy 的 get/set 方法实现
let data = {
msg: 'hello',
count: 0
}
let vm = new Proxy(data,{
// 执行代理行为的函数
// 当访问 vm 的成员会执行
get(target,key){
console.log('get,key',key, target[key])
},
set(target,key,newValue){
console.log('set,key',key,newValue)
if(target[key]=== newValue){
return
}
target[key] = newValue
document.getElementById("app").textContent = target[key]
}
})
vm.msg = 'hello Word'
console.log(vm.msg)