响应式原理篇--Vue2和Vue3
Vue2的响应式:
我们知道Vue2的响应式是通过Object.defineProperty的getter 和 setter 函数实现的。也就是数据劫持,数据劫持就是响应式。
//这里我们尝试手写一个简单的Vue2的响应式
let person = {name:"zs",age:18};
let p = {};
//这里只对其中person对象中的一个参数进行拦截,其他参数类推就行
Object.defineProperty(p,"name",{
get(){
console.log("someone read the variable");
return person.name;
},
set(value){
console.log("someone changed the variable")
person.name = value
}
})
//在这里我们可以看见基本的看见,对Person这个对象读取和修改做了一个拦截,也就是响应式。
通过内置的Object.defineProperty这个api,Vue2实现了数据视图的响应式更新。
Vue3的响应式:
我们接着看到Vue3,Vue3我们知道是组合式api,将所有的数据、函数、生命周期全写在setup中.
<scrpit setup>
let name = ref("zs");
let age = ref(18);
let hobby = reactive(["reading","study"])
//用ref和reactive将数据转为反射对象或是代理对象来实现数据视图的更新
</script>
我们再来尝试写一下Vue3的响应式基本实现:
//思考一下:为什么Vue3是通过代理Proxy来实现响应式的,为什么不用原来的Vue2的Object.defineProperty来实现数据劫持。
let person = {name:"zs",age:18};
let p = new Proxy(person,{});//理解为,去代理Person这个对象
//下图可以看见p和perosn,通过在控制台的尝试,可以知道,p这个Proxy对象是可以直接去完成增删改查操作。但这不是响应式,响应式是要劫持,拦截数据。
let p = new Proxy(person,{
get(target,propName ){//target 是这个源数据,propName是读的参数
console.log("someone read the value");
return Reflect.get(target,propName);
},
set(target,propName,value){
console.log("someone change or add some value")
return Reflect.set(target,propName,value)//value是修改或添加的那个值,name:"zs"->name:"ls"
},
deleteProperty(target,propName){
console.log("someone delete some propName");
return Reflect.deleteProperty(target,propName)
}
})
这个就是Vue3响应式的基本原理。
Exg:
这样不难看出,Vue2对于一个对象的删除和添加是无法进行拦截的,当然Vue2也给出来解决办法。
let person = {name:"zs",age:18};
//添加一个参数
addPropName(){
this.$set(this.person,"sex","woman");
//或者是
Vue.set(this.person,"sex","woman");
}
当然我这段对于Vue2,Vue3的响应式的解读是十分浅薄的。就好像自己写完这些都有一些存疑。后面会陆续补充Reflect和Proxy