ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

vue3.0源码核心--reactivity核心模块reactive

2021-07-05 19:02:07  阅读:204  来源: 互联网

标签:createReactiveObject TargetType return target -- reactive 源码 __


reactivity核心模块reactive


前言

上文我们学习了vue.3.1响应式系统reactivity,今天我们来系统学习下核心模块reactive源码
Vue3中响应数据核心是 reactive , reactive 中的实现是由 proxy 加 effect 组合,先来看一下 reactive 方法的定义

一、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 创建 observe
  return createReactiveObject(
    target, 
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}

二、createReactiveObject

createReactiveObject的作用是将target转化为响应式对象,话不多说上代码
代码版本3.1.4


function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>
  proxyMap: WeakMap<Target, any>
) {
  // 被转化的target必须是object
  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
    if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }

  // target already has corresponding Proxy 目标已经有相应的代理
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // only a whitelist of value types can be observed.白名单
  //只有target在可转化类型白名单里才会进行转化,否则直接返回target
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  // 转化proxy对象,并将转化后的对象挂载到target的__v_readonly(只读模式)或__v_reactive(非只读模式)属性上
  const proxy = new Proxy(
    target,
  // Set、WeakSet、Map、WeakMap类型用的collectionHandlers,其他对象类型使用baseHandlers
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
  )
  proxyMap.set(target, proxy)
  return proxy
}

那么在这里3.1是优化了3.0的createReactiveObject方法内可转化类型白名单方法的实现,会校验target的__v_skip是否为true、target类型是否在白名单里、target是否为冻结对象,同时满足才会继续转化

三、目标对象

代码如下(版本3.1.4):

// 同时满足3个条即为可以观察的目标对象
// 1. 没有打上__v_skip标记
// 2. 是可以观察的值类型
// 3. 没有被frozen
function getTargetType(value: Target) {
  return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
    ? TargetType.INVALID
    : targetTypeMap(toRawType(value))
}

// 可以被观察的值类型
function targetTypeMap(rawType: string) {
  switch (rawType) {
    case 'Object':
    case 'Array':
      return TargetType.COMMON
    case 'Map':
    case 'Set':
    case 'WeakMap':
    case 'WeakSet':
      return TargetType.COLLECTION
    default:
      return TargetType.INVALID
  }
}
const enum TargetType {
  INVALID = 0,
  COMMON = 1,
  COLLECTION = 2
}

这里对于3.0有一些改变,3.0是直接判断是否是可以观察的值类型,并没有区分COMMON类型与COLLECTION类型。

总结

reactive 是做为整个响应式的入口,负责处理目标对象是否可观察以及是否已被观察的逻辑,最后使用 Proxy 进行目标对象的代理,Proxy 重点的逻辑处理在 Handlers ,下面我们会介绍collectionHandlers与baseHandlers,并逐步对于前置知识进行补充

标签:createReactiveObject,TargetType,return,target,--,reactive,源码,__
来源: https://blog.csdn.net/weixin_50077637/article/details/118494104

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有