响应式原理--Vue2和Vue3

50 阅读2分钟

响应式原理篇--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)
    }
})

image.png 这个就是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