Skip to content

Commit 02c6924

Browse files
authored
refactor(reactivity): encapsulate reactive handlers in class (#8586)
reactive obj create has a huge positive impact (200% - 700%) get/set reactive obj props has a small negative impact (1% - 5%)
1 parent e7d5a41 commit 02c6924

File tree

1 file changed

+55
-58
lines changed

1 file changed

+55
-58
lines changed

Diff for: packages/reactivity/src/baseHandlers.ts

+55-58
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
hasChanged,
2727
isArray,
2828
isIntegerKey,
29-
extend,
3029
makeMap
3130
} from '@vue/shared'
3231
import { isRef } from './ref'
@@ -45,11 +44,6 @@ const builtInSymbols = new Set(
4544
.filter(isSymbol)
4645
)
4746

48-
const get = /*#__PURE__*/ createGetter()
49-
const shallowGet = /*#__PURE__*/ createGetter(false, true)
50-
const readonlyGet = /*#__PURE__*/ createGetter(true)
51-
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)
52-
5347
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations()
5448

5549
function createArrayInstrumentations() {
@@ -91,8 +85,15 @@ function hasOwnProperty(this: object, key: string) {
9185
return obj.hasOwnProperty(key)
9286
}
9387

94-
function createGetter(isReadonly = false, shallow = false) {
95-
return function get(target: Target, key: string | symbol, receiver: object) {
88+
class BaseReactiveHandler implements ProxyHandler<Target> {
89+
constructor(
90+
protected readonly _isReadonly = false,
91+
protected readonly _shallow = false
92+
) {}
93+
94+
get(target: Target, key: string | symbol, receiver: object) {
95+
const isReadonly = this._isReadonly,
96+
shallow = this._shallow
9697
if (key === ReactiveFlags.IS_REACTIVE) {
9798
return !isReadonly
9899
} else if (key === ReactiveFlags.IS_READONLY) {
@@ -155,11 +156,12 @@ function createGetter(isReadonly = false, shallow = false) {
155156
}
156157
}
157158

158-
const set = /*#__PURE__*/ createSetter()
159-
const shallowSet = /*#__PURE__*/ createSetter(true)
159+
class MutableReactiveHandler extends BaseReactiveHandler {
160+
constructor(shallow = false) {
161+
super(false, shallow)
162+
}
160163

161-
function createSetter(shallow = false) {
162-
return function set(
164+
set(
163165
target: object,
164166
key: string | symbol,
165167
value: unknown,
@@ -169,7 +171,7 @@ function createSetter(shallow = false) {
169171
if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
170172
return false
171173
}
172-
if (!shallow) {
174+
if (!this._shallow) {
173175
if (!isShallow(value) && !isReadonly(value)) {
174176
oldValue = toRaw(oldValue)
175177
value = toRaw(value)
@@ -197,51 +199,50 @@ function createSetter(shallow = false) {
197199
}
198200
return result
199201
}
200-
}
201202

202-
function deleteProperty(target: object, key: string | symbol): boolean {
203-
const hadKey = hasOwn(target, key)
204-
const oldValue = (target as any)[key]
205-
const result = Reflect.deleteProperty(target, key)
206-
if (result && hadKey) {
207-
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
203+
deleteProperty(target: object, key: string | symbol): boolean {
204+
const hadKey = hasOwn(target, key)
205+
const oldValue = (target as any)[key]
206+
const result = Reflect.deleteProperty(target, key)
207+
if (result && hadKey) {
208+
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
209+
}
210+
return result
208211
}
209-
return result
210-
}
211212

212-
function has(target: object, key: string | symbol): boolean {
213-
const result = Reflect.has(target, key)
214-
if (!isSymbol(key) || !builtInSymbols.has(key)) {
215-
track(target, TrackOpTypes.HAS, key)
213+
has(target: object, key: string | symbol): boolean {
214+
const result = Reflect.has(target, key)
215+
if (!isSymbol(key) || !builtInSymbols.has(key)) {
216+
track(target, TrackOpTypes.HAS, key)
217+
}
218+
return result
219+
}
220+
ownKeys(target: object): (string | symbol)[] {
221+
track(
222+
target,
223+
TrackOpTypes.ITERATE,
224+
isArray(target) ? 'length' : ITERATE_KEY
225+
)
226+
return Reflect.ownKeys(target)
216227
}
217-
return result
218-
}
219-
220-
function ownKeys(target: object): (string | symbol)[] {
221-
track(target, TrackOpTypes.ITERATE, isArray(target) ? 'length' : ITERATE_KEY)
222-
return Reflect.ownKeys(target)
223228
}
224229

225-
export const mutableHandlers: ProxyHandler<object> = {
226-
get,
227-
set,
228-
deleteProperty,
229-
has,
230-
ownKeys
231-
}
230+
class ReadonlyReactiveHandler extends BaseReactiveHandler {
231+
constructor(shallow = false) {
232+
super(true, shallow)
233+
}
232234

233-
export const readonlyHandlers: ProxyHandler<object> = {
234-
get: readonlyGet,
235-
set(target, key) {
235+
set(target: object, key: string | symbol) {
236236
if (__DEV__) {
237237
warn(
238238
`Set operation on key "${String(key)}" failed: target is readonly.`,
239239
target
240240
)
241241
}
242242
return true
243-
},
244-
deleteProperty(target, key) {
243+
}
244+
245+
deleteProperty(target: object, key: string | symbol) {
245246
if (__DEV__) {
246247
warn(
247248
`Delete operation on key "${String(key)}" failed: target is readonly.`,
@@ -252,22 +253,18 @@ export const readonlyHandlers: ProxyHandler<object> = {
252253
}
253254
}
254255

255-
export const shallowReactiveHandlers = /*#__PURE__*/ extend(
256-
{},
257-
mutableHandlers,
258-
{
259-
get: shallowGet,
260-
set: shallowSet
261-
}
256+
export const mutableHandlers: ProxyHandler<object> =
257+
/*#__PURE__*/ new MutableReactiveHandler()
258+
259+
export const readonlyHandlers: ProxyHandler<object> =
260+
/*#__PURE__*/ new ReadonlyReactiveHandler()
261+
262+
export const shallowReactiveHandlers = /*#__PURE__*/ new MutableReactiveHandler(
263+
true
262264
)
263265

264266
// Props handlers are special in the sense that it should not unwrap top-level
265267
// refs (in order to allow refs to be explicitly passed down), but should
266268
// retain the reactivity of the normal readonly object.
267-
export const shallowReadonlyHandlers = /*#__PURE__*/ extend(
268-
{},
269-
readonlyHandlers,
270-
{
271-
get: shallowReadonlyGet
272-
}
273-
)
269+
export const shallowReadonlyHandlers =
270+
/*#__PURE__*/ new ReadonlyReactiveHandler(true)

0 commit comments

Comments
 (0)