reactive
定义: 接收一个普通对象然后返回该普通对象的响应式代理。等同于 2.x 的 Vue.observable()
const obj = reactive({ count: 0 })
响应式转换是“深层的”:会影响对象内部所有嵌套的属性。基于 ES2015 的 Proxy 实现,返回的代理对象不等于原始对象。建议仅使用代理对象而避免依赖原始对象。
更多API https://vue3js.cn/vue-composition-api/#reactive
正文
Vue3中响应数据核心是 reactive , reactive 中的实现是由 proxy 加 effect 组合,先来看一下 reactive 方法的定义
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>export function reactive(target: object) {// if trying to observe a readonly proxy, return the readonly version.// 如果目标对象是一个只读的响应数据,则直接返回目标对象if (target && (target as Target).__v_isReadonly) {return target}// 否则调用 createReactiveObject 创建 observereturn createReactiveObject(target,false,mutableHandlers,mutableCollectionHandlers)}
createReactiveObject 创建 observe
// Target 目标对象// isReadonly 是否只读// baseHandlers 基本类型的 handlers// collectionHandlers 主要针对(set、map、weakSet、weakMap)的 handlersfunction createReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>) {// 如果不是对象if (!isObject(target)) {// 在开发模式抛出警告,生产环境直接返回目标对象if (__DEV__) {console.warn(`value cannot be made reactive: ${String(target)}`)}return target}// target is already a Proxy, return it.// exception: calling readonly() on a reactive object// 如果目标对象已经是个 proxy 直接返回if (target.__v_raw && !(isReadonly && target.__v_isReactive)) {return target}// target already has corresponding Proxyif (hasOwn(target, isReadonly ? ReactiveFlags.readonly : ReactiveFlags.reactive)) {return isReadonly ? target.__v_readonly : target.__v_reactive}// only a whitelist of value types can be observed.// 检查目标对象是否能被观察, 不能直接返回if (!canObserve(target)) {return target}// 使用 Proxy 创建 observeconst observed = new Proxy(target,collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers)// 打上相应标记def(target,isReadonly ? ReactiveFlags.readonly : ReactiveFlags.reactive,observed)return observed}// 同时满足3个条即为可以观察的目标对象// 1. 没有打上__v_skip标记// 2. 是可以观察的值类型// 3. 没有被frozenconst canObserve = (value: Target): boolean => {return (!value.__v_skip &&isObservableType(toRawType(value)) &&!Object.isFrozen(value))}// 可以被观察的值类型const isObservableType = /*#__PURE__*/ makeMap('Object,Array,Map,Set,WeakMap,WeakSet')
结语
看到这里我们大概清楚 reactive 是做为整个响应式的入口,负责处理目标对象是否可观察以及是否已被观察的逻辑,最后使用 Proxy 进行目标对象的代理,对 es6 Proxy 概念清楚的同学应该 Proxy 重点的逻辑处理在 Handlers , 接下来我们就一起去看看各种 Handlers
如果你对 Proxy 还不理解,可以点这里学习
