vue3.2 reactivity 之 (baseHandlers && collectionHandlers) API源码解析


在代码块中我会添加注释,方便大家理解,配合vue文档看效果更佳
本篇针对 /packages/reactivity/src/baseHandlers .ts 与 /packages/reactivity/src/collectionHandlers.ts

--------- baseHandlers ----------

get

首先来看一下所有的get方法定义

const get = /*#__PURE__*/ createGetter()
const shallowGet = /*#__PURE__*/ createGetter(false, true)
const readonlyGet = /*#__PURE__*/ createGetter(true)
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)

可以看到,所有的get方法都由 createGetter创建而来


createGetter

//创建get方法
// isReadonly 是否只读,shallow是否是浅层
function createGetter(isReadonly = false, shallow = false) {
  return function get(target: Target, key: string | symbol, receiver: object) {
    //当获取 key = __v_isReactive 时,返回 isReadonly取反,因为只有 readonly, reactive
    if (key === ReactiveFlags.IS_REACTIVE) {
      return !isReadonly
    // 当获取 key = __v_isReadonly 时,返回 isReadonly
    } else if (key === ReactiveFlags.IS_READONLY) {
      return isReadonly
    // 当获取 key = __v_raw 时,并且已在对应的proxy缓存map中存在,则直接返回
    } else if (
      key === ReactiveFlags.RAW &&
      receiver ===
        (isReadonly ? (shallow ? shallowReadonlyMap : readonlyMap) : (shallow ? shallowReactiveMap : reactiveMap) ).get(target)
    ) {
      return target
    }
	//判断是否为数组, 实际就是调用 Array.isArray(target)
    const targetIsArray = isArray(target)
	//不是只读 且 是数组类型 且 key 值 在 **arrayInstrumentations** 中
    if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
      return Reflect.get(arrayInstrumentations, key, receiver)
    }
	//拿到结果
    const res = Reflect.get(target, key, receiver)
	// 判断是否是 symbol
	// builtInSymbols: symbol 类 上的一些symbol类型的属性,例如迭代器 symbol.iterator
    if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
      return res
    }
	//如果不是只读的,则进行依赖收集
    if (!isReadonly) {
      track(target, TrackOpTypes.GET, key)
    }
	//如果是浅层的,则直接返回
    if (shallow) {
      return res
    }
	//如果是一个ref
	// 如果target不是数组,或者 key不是整数, 则返回 res.value
    // 其余情况返回res
    if (isRef(res)) {
      const shouldUnwrap = !targetIsArray || !isIntegerKey(key)
      return shouldUnwrap ? res.value : res
    }

    if (isObject(res)) {  
      return isReadonly ? readonly(res) : reactive(res)
    }

    return res
  }
}

判断:key = ReactiveFlags.IS_REACTIVE ,例:在 isReactive, 中被使用。
判断:key = ReactiveFlags.IS_READONLY,例:在 isReadonly 中被使用。
判断:key = ReactiveFlags.RAW ,例:在 toRaw 中被使用。
判断:不是只读 且 是数组类型 且 key 值 在 arrayInstrumentations 中, 则直接返回arrayInstrumentations对应key的结果。(arrayInstrumentations是对数组一些方法的重写,下面会介绍到)。
当以上情况都不满足,则调用Reflect反射先拿到结果res。
builtInSymbols
在这里插入图片描述
isNonTrackableKeys

const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`)
{
	__proto__: true,
	__v_isRef: true,
	__isVue: true
}

判断是否是symbol类,是则判断是否在 builtInSymbols中,反之判断是否在isNonTrackableKeys,是则直接返回。

接着判断是否为只读,否则进行依赖收集,判断是否为浅层,是则直接返回。
判断是否为ref,是则 如果 target不是数组,或者 key不是整数,返回res.value
例如:const arr = reactive([ 1,2, ref(3) ]) 这里取 arr[3] 时就返回 3

然后判断res是否为对象,在根据 isReadonly 去判断用 readonly(res) 或者 reactive(res) 进行转换。
也就是当出现嵌套对象时,只有用到的时候才会去把它转化成响应式proxy对象。


arrayInstrumentations

const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations()
function createArrayInstrumentations() {
  const instrumentations: Record<string, Function> = {}
  // 对下标敏感的方法重写,收集依赖
  ;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      //获取原始数组
      const arr = toRaw(this) as any
      //收集每个下标依赖 例:targetMap: { arr: { 0:{ effect }, 1: { effect } } }
      for (let i = 0, l = this.length; i < l; i++) {
        track(arr, TrackOpTypes.GET, i + '')
      }
      // 执行对应方法获取值
      const res = arr[key](...args)
      // 如果未找到,有可能args参数中存在响应式proxy对象,对args遍历进行toRaw,并重新执行
      if (res === -1 || res === false) {
        return arr[key](...args.map(toRaw))
      } else {
        return res
      }
    }
  })
  //对数组长度敏感的方法进行重写,已防某些情况下出现死循环(因为对length获取或赋值会走依赖的收集与更新)
  ;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      pauseTracking() // 暂停依赖收集
      const res = (toRaw(this) as any)[key].apply(this, args) //执行对应方法
      resetTracking() // 重置依赖收集
      return res
    }
  })
  return instrumentations
}

对数组长度敏感的方法进行重写,已防某些情况下出现死循环。来解释一下,我们拿push方法举例
const res = (toRaw(this) as any)[key].apply(this, args)
以上apply传进去的this是我们的响应式对象,当push方法执行时,会从this中获取length,以及对length进行更新,假如不暂停依赖的收集。我们看个场景:


set

const set = /*#__PURE__*/ createSetter()
const shallowSet = /*#__PURE__*/ createSetter(true)

createSetter

// 创建set方法, shallow 参数标识是否为浅层
function createSetter(shallow = false) {
  return function set(
    target: object,
    key: string | symbol,
    value: unknown,
    receiver: object
  ): boolean {
    let oldValue = (target as any)[key]	//获取旧值
    //非浅层 且 value非只读
    if (!shallow && !isReadonly(value)) {
      value = toRaw(value) 
      oldValue = toRaw(oldValue) 
      //target不是数组, oldValue是ref, value不是ref
      if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
        oldValue.value = value //赋值操作
        return true //返回true结束
      }
    } else {
      // in shallow mode, objects are set as-is regardless of reactive or not
    }
	// hadKey 进行取值有效判断,即key是否在target上存在
    const hadKey =
      isArray(target) && isIntegerKey(key)
        ? Number(key) < target.length
        : hasOwn(target, key)
    const result = Reflect.set(target, key, value, receiver) //获取结果
    // 保证target被代理过
    if (target === toRaw(receiver)) {
      if (!hadKey) {
        trigger(target, TriggerOpTypes.ADD, key, value)
      } else if (hasChanged(value, oldValue)) {
        trigger(target, TriggerOpTypes.SET, key, value, oldValue)
      }
    }
    return result
  }
}

首先对oldValue是一个ref进行处理直接 .value赋值, 则会触发ref对应的依赖。
hadkey 判断 key是否在target上,以便 trigger时,通知是 ADD 还是 SET


deleteProperty

delete 操作符的捕捉器

function deleteProperty(target: object, key: string | symbol): boolean {
  const hadKey = hasOwn(target, key)	//判断是否属于target
  const oldValue = (target as any)[key]		//获取旧值
  const result = Reflect.deleteProperty(target, key) //结果
  //成功且属于target,触发依赖
  if (result && hadKey) {
    trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
  }
  return result
}

has

in 操作符的捕捉器

function has(target: object, key: string | symbol): boolean {
  const result = Reflect.has(target, key) //结果
  // 如果不是Symbol,或者不属于Symbol上的Symbol属性,则收集依赖
  if (!isSymbol(key) || !builtInSymbols.has(key)) {
    track(target, TrackOpTypes.HAS, key)
  }
  return result
}

ownKeys

Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器

function ownKeys(target: object): (string | symbol)[] {
  //收集依赖
  track(target, TrackOpTypes.ITERATE, isArray(target) ? 'length' : ITERATE_KEY)
  return Reflect.ownKeys(target)
}

mutableHandlers

export const mutableHandlers: ProxyHandler<object> = {
  get,
  set,
  deleteProperty,
  has,
  ownKeys
}

readonlyHandlers

export const readonlyHandlers: ProxyHandler<object> = {
  get: readonlyGet,
  set(target, key) {
    if (__DEV__) {
      console.warn(
        `Set operation on key "${String(key)}" failed: target is readonly.`,
        target
      )
    }
    return true
  },
  deleteProperty(target, key) {
    if (__DEV__) {
      console.warn(
        `Delete operation on key "${String(key)}" failed: target is readonly.`,
        target
      )
    }
    return true
  }
}

readonlyHandlers中,set 与 deleteProperty 不做任何操作,就是不允许修改和删除。
在dev环境中会有对应警告。


shallowReactiveHandlers

// extend 是一个工具函数,可以理解为合并对象
export const shallowReactiveHandlers = /*#__PURE__*/ extend(
  {},
  mutableHandlers,
  {
    get: shallowGet,
    set: shallowSet
  }
)

mutableHandlers 基础上,将getset 替换成 shallowGetshallowSet


shallowReadonlyHandlers

export const shallowReadonlyHandlers = /*#__PURE__*/ extend(
  {},
  readonlyHandlers,
  {
    get: shallowReadonlyGet
  }
)

readonlyHandlers 基础上,将get 替换成 shallowReadonlyGet


--------- collectionHandlers----------

export type CollectionTypes = IterableCollections | WeakCollections

type IterableCollections = Map<any, any> | Set<any>
type WeakCollections = WeakMap<any, any> | WeakSet<any>
type MapTypes = Map<any, any> | WeakMap<any, any>
type SetTypes = Set<any> | WeakSet<any>

toShallow

const toShallow = <T extends unknown>(value: T): T => value

shallow转换,直接返回value。


getProto

const getProto = <T extends CollectionTypes>(v: T): any =>
  Reflect.getPrototypeOf(v)

获取原型的通用方法


mutableCollectionHandlers

shallowCollectionHandlers

readonlyCollectionHandlers

shallowReadonlyCollectionHandlers

export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
  get: /*#__PURE__*/ createInstrumentationGetter(false, false)
}

export const shallowCollectionHandlers: ProxyHandler<CollectionTypes> = {
  get: /*#__PURE__*/ createInstrumentationGetter(false, true)
}

export const readonlyCollectionHandlers: ProxyHandler<CollectionTypes> = {
  get: /*#__PURE__*/ createInstrumentationGetter(true, false)
}

export const shallowReadonlyCollectionHandlers: ProxyHandler<CollectionTypes> =
  {
    get: /*#__PURE__*/ createInstrumentationGetter(true, true)
  }

所有的Handlers都只有一个get方法,且都有 createInstrumentationGetter 创建。
因为对于 Map,WeakMap,Set,WeakSet, 无论是取值或者是赋值等操作都是调用其方法。


createInstrumentationGetter

// isReadonly 是否只读, shallow 是否浅层
function createInstrumentationGetter(isReadonly: boolean, shallow: boolean) {
	//判断使用哪个 Instrumentations
	// Instrumentations 由 createInstrumentations创建
	// Instrumentations 为 get,set,add,等的方法集
  const instrumentations = shallow
    ? isReadonly
      ? shallowReadonlyInstrumentations
      : shallowInstrumentations
    : isReadonly
    ? readonlyInstrumentations
    : mutableInstrumentations

  return (
    target: CollectionTypes,
    key: string | symbol,
    receiver: CollectionTypes
  ) => {
    // 这部分与baseHandlers基本一样,对于一些特殊属性进行取值
    //获取是否是reactive
    if (key === ReactiveFlags.IS_REACTIVE) {
      return !isReadonly
     //获取是否是readonly
    } else if (key === ReactiveFlags.IS_READONLY) {
      return isReadonly
     //获取是否原始值
    } else if (key === ReactiveFlags.RAW) {
      return target
    }
    //第一个参数
	//如果 key 在 instrumentations 中,且在target中, 则返回对应的 instrumentations,反之正常返回target
    return Reflect.get(
      hasOwn(instrumentations, key) && key in target
        ? instrumentations
        : target,
      key,
      receiver
    )
  }
}

首先是根据参数获取对应的instrumentations (集合或字典对应的方法集)。
接着return 真正的get函数,进行特殊取值的判断, 在返回反射get时,对第一个参数target进行判断,如果是调用集合或字典上对应的方法,则第一个参数为 instrumentations,否则正常使用target。
目的就是为了能调用 instrumentations 中各种重写后的方法。
接着我们看 Instrumentations 的由来 。

const [
  mutableInstrumentations,
  readonlyInstrumentations,
  shallowInstrumentations,
  shallowReadonlyInstrumentations
] = /* #__PURE__*/ createInstrumentations()

createInstrumentations 创建而来的数组包裹。


createInstrumentations

function createInstrumentations() {
	// 定义 mutableInstrumentations
  const mutableInstrumentations: Record<string, Function> = {
    get(this: MapTypes, key: unknown) {
      return get(this, key)
    },
    get size() {
      return size(this as unknown as IterableCollections)
    },
    has,
    add,
    set,
    delete: deleteEntry,
    clear,
    forEach: createForEach(false, false)
  }
  // 定义 shallowInstrumentations
  const shallowInstrumentations: Record<string, Function> = {
    get(this: MapTypes, key: unknown) {
      return get(this, key, false, true)
    },
    get size() {
      return size(this as unknown as IterableCollections)
    },
    has,
    add,
    set,
    delete: deleteEntry,
    clear,
    forEach: createForEach(false, true)
  }
   // 定义 readonlyInstrumentations
  const readonlyInstrumentations: Record<string, Function> = {
    get(this: MapTypes, key: unknown) {
      return get(this, key, true)
    },
    get size() {
      return size(this as unknown as IterableCollections, true)
    },
    has(this: MapTypes, key: unknown) {
      return has.call(this, key, true)
    },
    add: createReadonlyMethod(TriggerOpTypes.ADD),
    set: createReadonlyMethod(TriggerOpTypes.SET),
    delete: createReadonlyMethod(TriggerOpTypes.DELETE),
    clear: createReadonlyMethod(TriggerOpTypes.CLEAR),
    forEach: createForEach(true, false)
  }
   // 定义 shallowReadonlyInstrumentations
  const shallowReadonlyInstrumentations: Record<string, Function> = {
    get(this: MapTypes, key: unknown) {
      return get(this, key, true, true)
    },
    get size() {
      return size(this as unknown as IterableCollections, true)
    },
    has(this: MapTypes, key: unknown) {
      return has.call(this, key, true)
    },
    add: createReadonlyMethod(TriggerOpTypes.ADD),
    set: createReadonlyMethod(TriggerOpTypes.SET),
    delete: createReadonlyMethod(TriggerOpTypes.DELETE),
    clear: createReadonlyMethod(TriggerOpTypes.CLEAR),
    forEach: createForEach(true, true)
  }

  const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator]
  iteratorMethods.forEach(method => {
    mutableInstrumentations[method as string] = createIterableMethod(
      method,
      false,
      false
    )
    readonlyInstrumentations[method as string] = createIterableMethod(
      method,
      true,
      false
    )
    shallowInstrumentations[method as string] = createIterableMethod(
      method,
      false,
      true
    )
    shallowReadonlyInstrumentations[method as string] = createIterableMethod(
      method,
      true,
      true
    )
  })

  return [
    mutableInstrumentations,
    readonlyInstrumentations,
    shallowInstrumentations,
    shallowReadonlyInstrumentations
  ]
}

可以看到,createInstrumentations 主要就是对各种 Instrumentations 进行各种方法的重写 (get,set,has,add,clear,delete,forEach),以及迭代方法的重写(keys,values,entries,Symbol.iterator)。接着我们在逐步介绍其中的方法。


get

function get(
  target: MapTypes,	// Map or WeakMAp
  key: unknown, // key
  isReadonly = false, //是否只读
  isShallow = false  //是否浅层
) {
  // 例如:reactive(Map) 中的 Map; readonly(reactive(Map)) 中的 reactive(Map)
  target = (target as any)[ReactiveFlags.RAW] 
  // target 为 map 则返回 Map; target 为 reactive(Map) 则返回 Map
  const rawTarget = toRaw(target) 
  const rawKey = toRaw(key) //获取key原始值
  // 当key不等于rawkey; 例如:key = reactive({}) 时, rawKey = {}
  if (key !== rawKey) {
  	//不是只读则对 rawTarget 中的 key 进行依赖收集
    !isReadonly && track(rawTarget, TrackOpTypes.GET, key)
  }
  //不是只读则对 rawTarget 中的 rawKey 进行依赖收集
  !isReadonly && track(rawTarget, TrackOpTypes.GET, rawKey)
  const { has } = getProto(rawTarget) //获取rawTarget原型中的has
  //获取对应转换方法
  const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive
  /*
  		当 key存在于rawTarget时,获取值并转换成对应的响应式对象
  		例如:
  		    const map = new Map( [ ['name', 'loookooo'] ] )
  			const reactiveMap = reactive(map)
  			reactiveMap.get('name')
  			此时   map 的结构等于 { 'name': 'loookooo' }
  				  target = map   rawTarget = map
  			       key = 'name'   rawkey = 'name'
	*/
  if (has.call(rawTarget, key)) {
    return wrap(target.get(key))
  /*
        当 key不存在于rawTarget时, rawKey存在于rawTarget时,获取值并转换成对应的响应式对象
  		例如:
  		    const map = new Map()
  			const reactiveMap = reactive(map)
  			const reactiveKey = reactive({ key: 'key' })
  		    const reactiveValue = reactive({ value: 'value' })
  			reactiveMap.set(reactiveKey, reactiveValue )
  			reactiveMap.get(reactiveKey)
  			此时   map 的结构等于 { { key: 'key'} : { value: 'value'} }
  				   target = map  rawTarget = map
  			       key = reactiveKey   rawkey = { key: 'key' }
  */
  } else if (has.call(rawTarget, rawKey)) {
    return wrap(target.get(rawKey))
   /*
        当 key不存在于rawTarget时, rawKey不存在于rawTarget时,
        target !== rawTarget 调用 target.get(key)
  		例如:
  		    const map = new Map()
			const key = { key: 'key' }
			const value = { value: 'value' }
			const reactiveKey = reactive(key)
			const reactiveValue = reactive(value)
			map.set(reactiveKey, reactiveValue)
			const reactiveMap = reactive(map)
			const readonlyMap = readonly(reactiveMap)
			readonlyMap.get(key)
  			此时   map 的结构等于 { reactiveKey  : reactiveValue  }
  				   target = reactiveMap  rawTarget = map
  			       key = { key: 'key' }   rawkey = { key: 'key' }
  */
  } else if (target !== rawTarget) {
    // readonly(reactive(Map))
    // 确保嵌套的反应式 `Map` 可以为自己进行跟踪
    target.get(key)
  }
}

获取rawTarget时会经过两次获取原始值,是为了出现readonly(reactive(Map)) 的情况。
key不等于rawkey时,对key进行依赖收集。 对rawkey进行依赖收集
例如:key = reactive({}),rawkey = {},这时当key或者rawkey发生变化时,都会触发各自依赖。
接着就是对各种情况进行处理,代码块中有详细分析。


has

function has(this: CollectionTypes, key: unknown, isReadonly = false): boolean {
  const target = (this as any)[ReactiveFlags.RAW]
  const rawTarget = toRaw(target)
  const rawKey = toRaw(key)
  if (key !== rawKey) {
    !isReadonly && track(rawTarget, TrackOpTypes.HAS, key)
  }
  !isReadonly && track(rawTarget, TrackOpTypes.HAS, rawKey)
  /*
  	const reactiveKey = reactive({ key: 'key' })
  	const map = new Map()
  	const reactiveMap = reactive(map)
  	reactiveMap.set(reactiveKey, 'value')
  	
  	reactiveKey in reactiveMap
  	此时:   map 结构 = { { key: 'key' } : 'value' }
  		target = map  rawTarget = map
  		key = reactiveKey  rawkey = {key:'key'}
  */
  return key === rawKey
    ? target.has(key)
    : target.has(key) || target.has(rawKey)
}

前面的处理与get差不多,都是获取原始值。然后对keyrawkey做判断,进行依赖收集。
返回时,当key不等于rawkey时,has(key) 不存在则返回 has(rawkey) , 代码块中已举例


size

function size(target: IterableCollections, isReadonly = false) {
  target = (target as any)[ReactiveFlags.RAW]
  !isReadonly && track(toRaw(target), TrackOpTypes.ITERATE, ITERATE_KEY)
  return Reflect.get(target, 'size', target)
}
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')

调用size的时候对ITERATE_KEY进行依赖收集。在调用一些迭代方法的时候会触发ITERATE_KEY收集的依赖,例如 keys,values等。


add

function add(this: SetTypes, value: unknown) {
  value = toRaw(value)
  const target = toRaw(this)
  const proto = getProto(target)
  const hadKey = proto.has.call(target, value)
  if (!hadKey) {
    target.add(value)
    trigger(target, TriggerOpTypes.ADD, value, value)
  }
  return this
}

获取原始值,判断是否已存在,不存在则触发ADD操作类型的依赖。


set

function set(this: MapTypes, key: unknown, value: unknown) {
  value = toRaw(value) //获取value原始值
  const target = toRaw(this) //获取this原始值
  const { has, get } = getProto(target) //获取target原型的 has,get

  let hadKey = has.call(target, key) //判断target是否存在key
  //如果不存在
  /*
	场景:
		const key = { key: 'key' }
		const map = new Map( [ key, 'value' ] )
		const reactiveKey = reactive(key)
		const reactiveMap = reactive( map  )
		reactiveMap.set(reactiveKey, 'newValue')
		此时:
			value = 'newValue'    target = map  
			key = reactiveKey  
			reactiveKey 不存在于 map
			则 key = toRaw(reactiveKey) = { key: 'key' }
			   hadKey = has.call(map, { key: 'key' }) = true
 */
  if (!hadKey) {
    key = toRaw(key) //获取key原始值,并赋值
    hadKey = has.cal(target, key) // 判断target是否存在key原始值
  } else if (__DEV__) {
    checkIdentityKeys(target, has, key)
  }
  //获取旧值
  const oldValue = get.call(target, key)
  //调用原始值target的set操作
  target.set(key, value)
  //不存在,则触发ADD操作类型依赖
  if (!hadKey) {
    trigger(target, TriggerOpTypes.ADD, key, value)
  //存在且新旧值不相同,则触发SET操作类型依赖
  } else if (hasChanged(value, oldValue)) {
    trigger(target, TriggerOpTypes.SET, key, value, oldValue)
  }
  return this
}

set时先判断key是否在target 原始值里,否则对key原始值再进行一次判断。
依据判断结果来触发ADD或者SET的操作类型依赖。


deleteEntry

function deleteEntry(this: CollectionTypes, key: unknown) {
  const target = toRaw(this) //获取this原始值
  const { has, get } = getProto(target) //获取原型的 has,get
  let hadKey = has.call(target, key) // 判断是否存在 key
  //不存在则对key原始值进一次判断
  if (!hadKey) {
    key = toRaw(ke)
    hadKey = has.call(target, key)
  } else if (__DEV__) {
    checkIdentityKeys(target, has, key)
  }
  //判断get方法是否存在,是则获取旧值。Set,WeakSet 没有 get 和 set 方法,所以旧值为undefined
  const oldValue = get ? get.call(target, key) : undefined
  // 执行delete操作,获取操作结果
  const result = target.delete(key)
  if (hadKey) {
    trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
  }
  return result
}

判断是否存在,获取旧值时区分Map,WeakMap 于 Set, WeakSet。
当存在时,则触发对应依赖。


clear

function clear(this: IterableCollections) {
  const target = toRaw(this) //获取this原始值
  const hadItems = target.size !== 0 //判断target中是否有元素
  //生产环境下为undefined
  const oldTarget = __DEV__
    ? isMap(target)
      ? new Map(target)
      : new Set(target)
    : undefined
   // 执行clear操作,获取操作结果
  const result = target.clear()
  //如果有元素,则触发对应依赖
  if (hadItems) {
    trigger(target, TriggerOpTypes.CLEAR, undefined, undefined, oldTarget)
  }
  return result
}

forEach

function createForEach(isReadonly: boolean, isShallow: boolean) {
  return function forEach(
    this: IterableCollections,
    callback: Function,
    thisArg?: unknown
  ) {
    const observed = this as any
    const target = observed[ReactiveFlags.RAW] //获取 observed.__v_raw
    const rawTarget = toRaw(target) //获取 target 原始值
    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive
    //对 ITERATE_KEY 进行依赖收集
    !isReadonly && track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY)
    //执行forEach并返回操作结果
    return target.forEach((value: unknown, key: unknown) => {
      //执行callback,转换value,key为响应式对象并带入
      return callback.call(thisArg, wrap(value), wrap(key), observed)
    })
  }
}

与前面size一样, forEach同样会对 ITERATE_KEY (迭代key) 进行依赖收集。


createReadonlyMethod

function createReadonlyMethod(type: TriggerOpTypes): Function {
  return function (this: CollectionTypes, ...args: unknown[]) {
    if (__DEV__) {
      const key = args[0] ? `on key "${args[0]}" ` : ``
      console.warn(
        `${capitalize(type)} operation ${key}failed: target is readonly.`,
        toRaw(this)
      )
    }
    return type === TriggerOpTypes.DELETE ? false : this
  }
}

创建只读方法。不做任何操作,直接返回false或this


createIterableMethod

function createIterableMethod(
  method: string | symbol,
  isReadonly: boolean,
  isShallow: boolean
) {
  return function (
    this: IterableCollections,
    ...args: unknown[]
  ): Iterable & Iterator {
    const target = (this as any)[ReactiveFlags.RAW]
    const rawTarget = toRaw(target)
    const targetIsMap = isMap(rawTarget) //判断是否是map
    //判断是否是成对遍历,即 key 与 value 一起
    const isPair =
      method === 'entries' || (method === Symbol.iterator && targetIsMap)
     //是否是keys方法且是Map类型
    const isKeyOnly = method === 'keys' && targetIsMap
    //执行操作记录结果
    const innerIterator = target[method](...args)
    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive
    //不是只读则对迭代key进行依赖收集
    !isReadonly &&
      track(
        rawTarget,
        TrackOpTypes.ITERATE,
        isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY
      )
    // 包装迭代器
    return {
      // iterator protocol
      next() {
        const { value, done } = innerIterator.next() //获取真实的结果
        return done
          ? { value, done }
          : {
          	  //判断是否成对,返回相应的响应式值
              value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
              done
            }
      },
      [Symbol.iterator]() {
        return this
      }
    }
  }
}

判断遍历的类型是 key和value,key,value。
非只读时收集依赖。
返回包装迭代器,其中获取真是遍历结果,并包装返回对应的响应式结果。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值