Skip to content

Commit

Permalink
refactor(reactive): 增加reactive代码注释
Browse files Browse the repository at this point in the history
  • Loading branch information
王建魁(wangjiankui) committed Jun 16, 2022
1 parent 0376dd8 commit 4528199
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 28 deletions.
20 changes: 14 additions & 6 deletions src/reactive/baseHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {
reactiveMap,
shallowReadonlyMap,
readonlyMap,
shallowReactiveMap, readonly, isReadonly
shallowReactiveMap,
readonly,
isReadonly
} from "./reactive";
import { track, trigger, pauseTracking, resetTracking } from "./effect";
import {isArray, isObject, isIntegerKey, hasOwn, isSymbol, makeMap, extend, hasChange} from "../shared";
import { isArray, isObject, isIntegerKey, hasOwn, isSymbol, makeMap, extend, hasChange } from "../shared";
import { isRef } from "./ref";
import { TriggerOpTypes, TrackOpTypes } from "./operations";

Expand All @@ -23,7 +25,8 @@ const builtInSymbols = new Set(
)
// 数组array
const arrayInstrumentations = createArrayInstrumentations()
// 对数组的操作进行了拦截

// 对数组的原型上的方法进行了拦截
function createArrayInstrumentations() {
const instrumentations: Record<string, Function> = {}
;(['indexOf', 'includes', 'lastIndexOf']).forEach(key => {
Expand All @@ -42,10 +45,10 @@ function createArrayInstrumentations() {
})
;(['push']).forEach(key => {
instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
// 暂停收集
// 暂停track 暂停后,不会进行track
pauseTracking()
const res = (toRaw(this) as any)[key].apply(this, args)
// 恢复收集
// 恢复track 重新开始收集依赖
resetTracking()
return res
}
Expand Down Expand Up @@ -105,6 +108,7 @@ function createGetter(isReadonly = false, shallow = false) {
return res
}

// isReadonly为true, 不进行track操作
if (!isReadonly) {
track(target, TrackOpTypes.GET, key)
}
Expand Down Expand Up @@ -136,6 +140,8 @@ function createGetter(isReadonly = false, shallow = false) {
}

if (isObject(res)) {
// 如果为对象类型,则进行深层次的递归
// ** proxy只能代理第一层对象,深层次嵌套对象要递归代理
return isReadonly ? readonly(res) : reactive(res)
}

Expand Down Expand Up @@ -167,6 +173,8 @@ function createSetter(shallow = false) {
oldValue.value = value
return true
}
} else {
// shallow为true,无论是否对象响应式,都按照原样处理
}
/* end */

Expand All @@ -181,7 +189,7 @@ function createSetter(shallow = false) {
if (!hadKey) {
// 派发更新 新增
trigger(target, TriggerOpTypes.ADD, key, value)
} else if (hasChange(value, oldValue)) {
} else if (hasChange(value, oldValue)) { // 判断value、oldValue有没有变化
// 派发更新 设置
trigger(target, TriggerOpTypes.SET, key, value, oldValue)
}
Expand Down
20 changes: 17 additions & 3 deletions src/reactive/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ export interface DebuggerOptions {
let shouldTrack = true
const trackStack: boolean[] = []

// 暂停收集
/*
* 暂停收集
* 将上一次的的shouldTrack状态push到 trackStack
* shouldTrack = false 暂停track收集
* */
export function pauseTracking() {
trackStack.push(shouldTrack)
shouldTrack = false
}

// 重置为上一次的状态
/*
* 恢复track
* 重置为上一次的状态
* */
export function resetTracking() {
const last = trackStack.pop()
shouldTrack = last === undefined ? true : last
Expand Down Expand Up @@ -76,6 +83,7 @@ export function effect<T>(fn: () => T): ReactiveEffectRunner {// fn 会立即执
return runner
}

// track 负责进行依赖收集
export function track(target: object, type:TrackOpTypes, key: unknown) {
if (!isTracking()) {
return
Expand All @@ -85,6 +93,8 @@ export function track(target: object, type:TrackOpTypes, key: unknown) {
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()))
}
// 获取下dep, 如果没有就创建一个新的
// dep = new Set()
let dep = depsMap.get(key)
if (!dep) {
depsMap.set(key, ( dep = createDep() /* 初始化 dep */ ))
Expand All @@ -94,18 +104,21 @@ export function track(target: object, type:TrackOpTypes, key: unknown) {
trackEffects(dep)
}

// trigger 负责进行派发更新
export function trigger(
target: object,
type: TriggerOpTypes,
key: unknown,
newValue?: unknown,
oldValue?: unknown
) {
// 从集合中拿不到deps 就不用派发更新了
// 1、尝试从weakMap中获取target 对应的 depsMap
const depsMap = targetMap.get(target)
if (!depsMap) {
return
}


const deps: (Dep | undefined)[] = []
// if (key === 'length' && isArray(target)) {
// depsMap.forEach((dep, key) => {
Expand Down Expand Up @@ -155,6 +168,7 @@ export function trigger(
* */
export function trackEffects(dep: Dep) {
if (shouldTrack) {
// 添加当前activeEffect到dep
dep.add(activeEffect!)
}
}
Expand Down
36 changes: 23 additions & 13 deletions src/reactive/reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { mutableHandlers, readonlyHandlers, shallowReactiveHandlers, shallowRead
import { mutableCollectionHandlers, readonlyCollectionHandlers, shallowCollectionHandlers } from "./collectionHandlers";
import { Ref, UnwrapRefSimple } from "./ref";

/********** TS类型声明 start ***********/
export enum ReactiveFlags {
RAW = '__v_raw', // 标记原始数据
IS_READONLY = '__v_isReadonly', // 标记只读数据
IS_REACTIVE = '__v_isReactive',
SKIP = '__v_skip'
IS_REACTIVE = '__v_isReactive', // 标记reactive
SKIP = '__v_skip' // 标记跳过
}

export interface Target {
Expand Down Expand Up @@ -46,6 +47,7 @@ export type DeepReadonly<T> = T extends Builtin
: T extends {}
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: Readonly<T>
/********** TS类型声明 end ***********/

function targetTypeMap(rawType: string) {
switch (rawType) {
Expand All @@ -71,46 +73,52 @@ function getTargetType(value: Target) {
: targetTypeMap(toRawType(value))
}

// 都是存储缓存用的
// 用于存储缓存用的
export const reactiveMap = new WeakMap<Target, any>()
export const shallowReactiveMap = new WeakMap<Target, any>()
export const readonlyMap = new WeakMap<Target, any>()
export const shallowReadonlyMap = new WeakMap<Target, any>()

// createReactiveObject 响应式转换函数
function createReactiveObject(
target: Target,
isReadonly: boolean, // 是否只读
baseHandlers: ProxyHandler<any>, // 处理普通对象数组的 proxy 的 handle
collectionHandlers: ProxyHandler<any>, // 处理普Map WeakMap Set WeakMap 的 proxy 的 handle
proxyMap: WeakMap<Target, any> // 缓存
) {
// 不是对象直接返回原目标
// 仅代理对象类型,不是对象直接返回原目标
if (!isObject(target)) {
return target
}
// 如果是个响应式直接返回响应式对象, readonly() 创建的响应式对象除外
if (target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE])) {
return target
}
// 先从缓存中查找
// 先从缓存中查找,已经代理过的直接返回
const existingProxy = proxyMap.get(target)
if (existingProxy) {
return existingProxy
}

// 如果target是被标记为原始数据 INVALID = 0
// __v_skip 也不会成为响应式
// 如果target是被标记为原始数据 INVALID = 0 或有__v_skip属性的不会成为响应式
// 相当于一个白名单,在名单里的数据类型不会变成响应式
const targetType = getTargetType(target)
if (targetType === TargetType.INVALID) {
return target
}

const proxy = new Proxy(
target,
targetType === TargetType.COLLECTION ? collectionHandlers: baseHandlers
)
// 根据不同的类型确定handler处理对象
// map、set类型取collectionHandlers
// object、array类型取baseHandlers
const handler = targetType === TargetType.COLLECTION ? collectionHandlers: baseHandlers
// 进行代理转换
const proxy = new Proxy(target, handler)

// 存入缓存中,下次就直接从缓存读取
proxyMap.set(target, proxy)

// 返回代理实例
return proxy
}

Expand All @@ -121,6 +129,7 @@ export function reactive(target: object) {
if (target && (target as Target)[ReactiveFlags.IS_READONLY]) {
return target
}
// 创建响应式对象
return createReactiveObject(
target,
false,
Expand All @@ -132,6 +141,7 @@ export function reactive(target: object) {

// 浅响应,只有根对象是响应式的
export function shallowReactive<T extends object>(target: T): T {
// 创建浅响应式对象
return createReactiveObject(
target,
false,
Expand All @@ -140,7 +150,7 @@ export function shallowReactive<T extends object>(target: T): T {
shallowReactiveMap
)
}

// 浅响应只读
export function shallowReadonly<T extends object>(target: T): Readonly<{ [K in keyof T]: UnwrapNestedRefs<T[K]> }> {
return createReactiveObject(
target,
Expand All @@ -150,7 +160,7 @@ export function shallowReadonly<T extends object>(target: T): Readonly<{ [K in k
shallowReadonlyMap
)
}

// 只读
export function readonly<T extends object>(target: T): DeepReadonly<UnwrapNestedRefs<T>> {
return createReactiveObject(
target,
Expand Down
8 changes: 4 additions & 4 deletions src/reactive/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,25 @@ export function unref<T>(ref:T | Ref<T>): T {
return isRef(ref) ? ref.value : ref
}

// 浅渲染
// 浅渲染, 创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的。
export function shallowRef(value?: unknown) {
return createRef(value, true)
}

// toRef
// toRef 可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
export function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]> {
return isRef(object[key]) ? object[key] : (new ObjectRefImpl(object, key) as any)
}

// toRefs
// toRefs 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref
export function toRefs<T extends object>(object: T): ToRefs<T> {
const res: any = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
res[key] = toRef(object, key)
}
return res
}

//customRef 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
return new CustomRefImpl(factory) as any
}
Expand Down
5 changes: 3 additions & 2 deletions src/runtime-core/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,12 @@ function baseCreateRenderer(
) => {
c1 = c1 || EMPTY_ARR
c2 = c2 || EMPTY_ARR
// 获得新旧节点的长度
const oldLength = c1.length
const newLength = c2.length
// 找到两个数组length最小的
// 找到两个数组length最小的,作为公共长度
const commonLength = Math.min(oldLength, newLength)
// 循环最小的
// 循环patch公共部分
for (let i = 0; i < commonLength; i++) {
const nextChild = c2[i]
patch(c1[i], nextChild as VNode, container, parentComponent)
Expand Down

0 comments on commit 4528199

Please sign in to comment.