1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
| // packages/reactivity/src/reactive.ts
// 可被代理的对象类型标记
const enum TargetType {
INVALID = 0, // 无效对象
COMMON = 1, // 普通对象
COLLECTION = 2, // 集合对象(Map, Set, WeakMap, WeakSet)
}
function getTargetType(value: unknown): TargetType {
// 如果对象被标记为原始值(不可代理),返回 INVALID
if (!isReadonly(value)) {
if (isPlainObject(value) || isArray(value)) {
return TargetType.COMMON
}
// 集合类型使用不同的代理策略
if (isCollectionType(value)) {
return TargetType.COLLECTION
}
}
return TargetType.INVALID
}
// isPlainObject: 判断是否是普通对象({} 或 new Object())
function isPlainObject(value: unknown): value is object {
if (isArray(value) || isCollectionType(value)) {
return false
}
return Object.prototype.toString.call(value) === '[object Object]'
}
// isCollectionType: 判断是否是集合类型
function isCollectionType(value: unknown): boolean {
const type = Object.prototype.toString.call(value)
return type === '[object Map]' ||
type === '[object Set]' ||
type === '[object WeakMap]' ||
type === '[object WeakSet]'
}
// reactive 函数
export function reactive<T extends object>(target: T): T {
// 如果目标已经是 readonly 的 reactive,直接返回
if (isReadonly(target)) {
return target as T
}
// 调用 createReactiveObject 创建代理
return createReactiveObject(
target,
false, // isReadonly
false, // isShallow
baseHandlers, // 普通对象的代理处理器
collectionHandlers // 集合对象的代理处理器
)
}
// 创建响应式代理的核心函数
function createReactiveObject(
target: object,
isReadonly: boolean,
isShallow: boolean,
baseHandlers: ProxyHandler<object>,
collectionHandlers: ProxyHandler<object>
) {
// 如果目标对象已经是响应式的,直接返回(避免重复代理)
if (isReactive(target)) {
return target as any
}
// 检查目标对象是否可以被代理
// 一些特殊对象如 Date、RegExp 不能被正确代理
if (!isValidProxyTarget(target)) {
console.warn(`value cannot be made reactive: ${target}`)
return target as any
}
// 根据目标类型选择处理器
// 集合类型(Map, Set)使用特殊的处理器
const proxyTargets =
Object.prototype.toString.call(target) === '[object Object]'
? baseHandlers
: collectionHandlers
// 创建并返回 Proxy
return new Proxy(target, proxyTargets)
}
// baseHandlers - 普通对象的代理处理器
export const baseHandlers: ProxyHandler<object> = {
get(target, key, receiver) {
// 如果读取的是 __v_isRef (在 reactive 中访问 ref 的值)
// 不建立依赖收集
const res = Reflect.get(target, key, receiver)
// 收集依赖
track(target, key)
// 如果是浅层响应式,直接返回结果
if (isShallow(key)) {
return res
}
// 如果是对象,递归包装为响应式
if (isObject(res)) {
return isReadonly
? // 深只读
readonly(res)
: // 深层响应式
reactive(res)
}
return res
},
set(target, key, value, receiver) {
const oldValue = target[key]
// 判断是新增还是修改
const hadKey = isArray(target)
? Number(key) < target.length
: hasOwn(target, key)
const result = Reflect.set(target, key, value, receiver)
// 触发更新
if (!hadKey) {
trigger(target, 'add', value)
} else if (hasChanged(value, oldValue)) {
trigger(target, 'set', value, oldValue)
}
return result
},
deleteProperty(target, key) {
const hadKey = hasOwn(target, key)
const oldValue = target[key]
const result = Reflect.deleteProperty(target, key)
if (hadKey) {
trigger(target, 'delete', undefined, oldValue)
}
return result
},
has(target, key) {
const result = Reflect.has(target, key)
track(target, key)
return result
},
ownKeys(target) {
// 遍历数组或对象的 key 时调用
// 需要处理数组的 length 依赖
track(target, isArray(target) ? 'length' : ITERATE_KEY)
return Reflect.ownKeys(target)
},
}
|