vue3-源码理解shallowRef和shallowReactive浅响应式

1.什么叫浅响应式?

  响应式:vue3中有ref和reactive两个方法,可以把数据变成响应式数据,响应式简单来讲就是能监测到数据得变化,从而去更新视图,使用ref和reactive创建得数据不管它得层级有多深,只要改变都能监测到。 

  例如:

   const person = ref({
        name:'zs',
        age:48,
        Child:{
            name:'lisi',
            age:18
        }
    })
    // 这种修改是能被监测到得,并能成功触发视图更新
    person.value.Child.age = 20;

 浅响应式:即只监测浅层数据得改变而不监测生成数据得改变,即只有最顶层数据得改变才能被监测到

2.shallowRef

 shallowRef是ref得浅层响应,使用shallowRef创建得数据只有根级别得才是响应式得,即使使用能使用value直接修改得才是响应式得  

   例如:

   const person = shallowRef({
        name:'zs',
        age:48,
        Child:{
            name:'lisi',
            age:18
        }
    })
    // 这种修改能成功修改Child.age得值,但是此时得修改没有被监测到,所以不能触发视图更新
    person.value.Child.age = 20;
   //如果想修改得同时更新视图,则需要如下修改
     person.value = {
        name:'zs',
        age:48,
        Child:{
            name:'lisi',
            age:20
        }
    }

 如果是一个普通类型得数据shallowRef和ref并没有区别,如:

  const count = shallowRef(12);

  count.value++ 

 shallowRef源码解析:

1.
export function shallowRef(value?: unknown) {
    //调用shallowRef方法时,实际调用得是createRef方法
    //value:传入得目标数据,true:表示是shallow方法
  return createRef(value, true)
}

2.
function createRef(rawValue: unknown, shallow: boolean) {
   //如果已经是ref响应式,则直接返回
  if (isRef(rawValue)) {
    return rawValue
  }
    //否则使用构造函数创建ref对象
  return new RefImpl(rawValue, shallow)
}

3.
class RefImpl<T> {
  private _value: T
  private _rawValue: T

  public dep?: Dep = undefined
  public readonly __v_isRef = true

  constructor(value: T, public readonly __v_isShallow: boolean) {
    //关键点在这里:__v_isShallow这个参数如果为false,则调用toReactive,而shallowRef方法中,该参数为true,则故能调用该方法处理传入得目标数据
    this._rawValue = __v_isShallow ? value : toRaw(value)
    this._value = __v_isShallow ? value : toReactive(value)
  }

  get value() {
    trackRefValue(this)
    return this._value
  }

  set value(newVal) {
    const useDirectValue =
      this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
    newVal = useDirectValue ? newVal : toRaw(newVal)
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal
      this._value = useDirectValue ? newVal : toReactive(newVal)
      triggerRefValue(this, newVal)
    }
  }
}    
toReactive:
 export const toReactive = <T extends unknown>(value: T): T =>
  //如果是object,则调用reactive
  isObject(value) ? reactive(value) : value
 //最终走到这里
 function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<Target, 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
  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 specific value types can be observed.
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  //重点:使用proxy代理传入得目标对象,此后该对象得任何更改都会被监测到
  const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
  )
  proxyMap.set(target, proxy)
  return proxy
}

3.shallowReactive 

shallowReactive是reactive得浅响应式,和shallowRef一样只有根级别数据是响应式得

  const person = reactive({
        name:'zs',
        age:48,
        Child:{
            name:'lisi',
            age:18
        }
    })
    // 根级别属是响应式得,修改后能触发视图更新
    person.name = '张三';
    // 更深层次得数据更新,不能监测到,不能触发视图更新
    person.Child.age = 20;

shallowReactive源码解析:

 

 

 

posted @ 2022-08-15 16:01  偶尔学习小菜鸟  阅读(1404)  评论(0)    收藏  举报