-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproxy.ts
145 lines (127 loc) · 3.57 KB
/
proxy.ts
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
import { execute } from './effect'
import {
IState,
IActions,
IInstance,
IStoreApi,
AnyArray,
AnyObject,
IProxyInstanceRes,
ObjectKey
} from './types'
// inDeepProxy: 防止在 Proxy 过程中触发副作用函数
let inDeepProxy = false
let currentRootKey: null | string = null
export function proxyInstance<
S extends IState,
A extends IActions<IProxyInstanceRes<S, A>>
>(instance: IInstance<S, A>): IProxyInstanceRes<S, A> {
const { state, actions, storeApi } = instance
return new Proxy<IProxyInstanceRes<S, A>>(instance as any, {
// storeApi => state => actions
get(_, prop: string) {
if (prop in storeApi) {
return storeApi[prop as ObjectKey<IStoreApi<S>>]
} else if (prop in state) {
return state[prop]
} else if (prop in actions) {
return actions[prop]
} else {
return undefined
}
},
set(_, prop: string, value: any) {
if (prop in storeApi) {
throw new Error(`${prop} 是 Store 自带的不允许被修改`)
} else if (prop in state) {
state[prop as ObjectKey<S | IState>] = value
return true
} else if (prop in actions) {
throw new Error(`${prop} 是 actions , 不允许在此被修改`)
} else {
throw new Error(`${prop} 不允许被修改或添加`)
}
}
})
}
export function proxyState<
S extends IState,
A extends IActions<IProxyInstanceRes<S, A>>
>(
instance: IInstance<S, A>,
targetObj: AnyArray | AnyObject,
rootKey: null | string = null
) {
const { isDeepWatch } = instance.options
return new Proxy(targetObj, {
set(target, prop: string, value) {
// 值不变就无需执行收集到的依赖
if (target[prop] === value) return true
if (isDeepWatch) {
if (inDeepProxy) {
target[prop] = value
return true
} else if (typeof value === 'object' && value !== null) {
currentRootKey = rootKey ?? prop
target[prop] = deepProxyState(instance, value)
currentRootKey = null
} else {
target[prop] = value
}
} else {
target[prop] = value
}
execute<S, A>(instance, rootKey ?? prop)
return true
}
})
}
export function deepProxyState<
S extends IState,
A extends IActions<IProxyInstanceRes<S, A>>
>(
instance: IInstance<S, A>,
rawTarget: AnyArray | AnyObject,
isRootObj = false
) {
// 设置根容器
const rootContainer: AnyArray | AnyObject = Array.isArray(rawTarget) ? [] : {}
function recursionProxy(
target: AnyObject | AnyArray,
upContainer: AnyArray | AnyObject,
isRoot = false
) {
for (const key in target) {
const value = target[key]
if (isRoot) {
currentRootKey = key
}
// 从底层开始逐上进行 proxy
/*
1.引用类型
1.1. 创建容器, 继续递归下去
1.2. 容器填充结束后进行 proxy 代理, 代理结果赋值给上一个容器
2.普通类型
直接赋值给上一个容器
*/
if (typeof value === 'object' && value !== null) {
const container = Array.isArray(value) ? [] : {}
recursionProxy(value, container)
upContainer[key] = proxyState<S, A>(instance, container, currentRootKey)
} else {
upContainer[key] = value
}
if (isRoot) {
currentRootKey = null
}
}
}
inDeepProxy = true
recursionProxy(rawTarget, rootContainer, isRootObj)
inDeepProxy = false
return proxyState<S, A>(
instance,
rootContainer,
isRootObj ? null : currentRootKey
)
}