vue3源码之reactive(vue.js源码全方位深入解析)
响应式对象reactive
何为响应式对象,在我看来就是一个可以进行拦截的对象,vue2采用的是Object.defineProperty,vue3采用的是Proxy。
单测
创建
src/reactivity/test/reactive.spec.ts。
import {reactive} from '../reactive'
describe("reactive", () => {
it("happy path", () => {
const origin = {
foo: 1
}
const obj = reactive(origin)
expect(obj).not.toBe(origin)
expect(obj.foo).toBe(1)
})
})
在vue3里,直接通过一个reactive(obj)函数创建一个proxy对象,返回的对象属性和值都和obj保持一致,但他们属于不同的两个对象。
代码实现
根据上面单测的功能点,我们开始一步步的来实现我们的reactive函数。
创建
./src/reactivity/reative.ts文件
1、导出一个reactive函数,接收用户传入的object数据。
export function reactive (raw) {
// write at this
}
2、返回一个Proxy实例
Proxy接收2个参数,第一个是需要劫持的object,第二个参数是一个options,这里我们只用设置get和set。
export function reactive (raw) {
return new Proxy(raw, {
get (target, key) {},
set (target, key, value) {}
})
}
3、处理get请求
当获取这个响应式对象的某个属性时调用,target就是获取的object,key就是获取的对象属性名称。
例如:obj.name,target代表obj,而key则代表name。
提示:这里的Reflect.get(target, key)其实就是获取target对象的key属性的值,最后在get中返回这个值即可。
get (target, key) {
const res = Reflect.get(target, key)
return res
}
4、处理set赋值
当执行了赋值操作时会调用set方法,target是操作的对象,key是操作对象的属性名称,value是赋值。
Reflect.set(target, key, value)即是给target对象的key属性赋值value,该执行结果是boolean,即代表赋值成功与否。
set (target, key, value) {
const res = Reflect.set(target, key, value)
return res
}
到这里,我们就成功创建了一个响应式对象,给这个响应式对象添加了set,和get操作。
总结
最后我们再一起来回顾一下这一节我们实现的代码及功能,在reactive.ts中我们导出了reactive函数,自身接收一个obj作为参数,并基于obj返回一个proxy对象,我们还简单的处理了一下proxy的get和set请求,后面我们将会对这个proxy对象进行完善,真正达到响应式。