feat(reactivity): support onTrack/onTrigger debug options for computed
This commit is contained in:
parent
b7ea7c1485
commit
5cea9a1d4e
@ -5,7 +5,12 @@ import {
|
|||||||
ref,
|
ref,
|
||||||
WritableComputedRef,
|
WritableComputedRef,
|
||||||
isReadonly,
|
isReadonly,
|
||||||
setComputedScheduler
|
setComputedScheduler,
|
||||||
|
DebuggerEvent,
|
||||||
|
toRaw,
|
||||||
|
TrackOpTypes,
|
||||||
|
ITERATE_KEY,
|
||||||
|
TriggerOpTypes
|
||||||
} from '../src'
|
} from '../src'
|
||||||
|
|
||||||
describe('reactivity/computed', () => {
|
describe('reactivity/computed', () => {
|
||||||
@ -200,6 +205,75 @@ describe('reactivity/computed', () => {
|
|||||||
expect(x.value).toBe(1)
|
expect(x.value).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('debug: onTrack', () => {
|
||||||
|
let events: DebuggerEvent[] = []
|
||||||
|
const onTrack = jest.fn((e: DebuggerEvent) => {
|
||||||
|
events.push(e)
|
||||||
|
})
|
||||||
|
const obj = reactive({ foo: 1, bar: 2 })
|
||||||
|
const c = computed(() => (obj.foo, 'bar' in obj, Object.keys(obj)), {
|
||||||
|
onTrack
|
||||||
|
})
|
||||||
|
expect(c.value).toEqual(['foo', 'bar'])
|
||||||
|
expect(onTrack).toHaveBeenCalledTimes(3)
|
||||||
|
expect(events).toEqual([
|
||||||
|
{
|
||||||
|
effect: c.effect,
|
||||||
|
target: toRaw(obj),
|
||||||
|
type: TrackOpTypes.GET,
|
||||||
|
key: 'foo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
effect: c.effect,
|
||||||
|
target: toRaw(obj),
|
||||||
|
type: TrackOpTypes.HAS,
|
||||||
|
key: 'bar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
effect: c.effect,
|
||||||
|
target: toRaw(obj),
|
||||||
|
type: TrackOpTypes.ITERATE,
|
||||||
|
key: ITERATE_KEY
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('debug: onTrigger', () => {
|
||||||
|
let events: DebuggerEvent[] = []
|
||||||
|
const onTrigger = jest.fn((e: DebuggerEvent) => {
|
||||||
|
events.push(e)
|
||||||
|
})
|
||||||
|
const obj = reactive({ foo: 1 })
|
||||||
|
const c = computed(() => obj.foo, { onTrigger })
|
||||||
|
|
||||||
|
// computed won't trigger compute until accessed
|
||||||
|
c.value
|
||||||
|
|
||||||
|
obj.foo++
|
||||||
|
expect(c.value).toBe(2)
|
||||||
|
expect(onTrigger).toHaveBeenCalledTimes(1)
|
||||||
|
expect(events[0]).toEqual({
|
||||||
|
effect: c.effect,
|
||||||
|
target: toRaw(obj),
|
||||||
|
type: TriggerOpTypes.SET,
|
||||||
|
key: 'foo',
|
||||||
|
oldValue: 1,
|
||||||
|
newValue: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
delete obj.foo
|
||||||
|
expect(c.value).toBeUndefined()
|
||||||
|
expect(onTrigger).toHaveBeenCalledTimes(2)
|
||||||
|
expect(events[1]).toEqual({
|
||||||
|
effect: c.effect,
|
||||||
|
target: toRaw(obj),
|
||||||
|
type: TriggerOpTypes.DELETE,
|
||||||
|
key: 'foo',
|
||||||
|
oldValue: 2
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('with scheduler', () => {
|
describe('with scheduler', () => {
|
||||||
// a simple scheduler similar to the main Vue scheduler
|
// a simple scheduler similar to the main Vue scheduler
|
||||||
const tick = Promise.resolve()
|
const tick = Promise.resolve()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ReactiveEffect } from './effect'
|
import { DebuggerOptions, ReactiveEffect } from './effect'
|
||||||
import { Ref, trackRefValue, triggerRefValue } from './ref'
|
import { Ref, trackRefValue, triggerRefValue } from './ref'
|
||||||
import { isFunction, NOOP } from '@vue/shared'
|
import { isFunction, NOOP } from '@vue/shared'
|
||||||
import { ReactiveFlags, toRaw } from './reactive'
|
import { ReactiveFlags, toRaw } from './reactive'
|
||||||
@ -101,12 +101,17 @@ class ComputedRefImpl<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computed<T>(getter: ComputedGetter<T>): ComputedRef<T>
|
|
||||||
export function computed<T>(
|
export function computed<T>(
|
||||||
options: WritableComputedOptions<T>
|
getter: ComputedGetter<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
|
): ComputedRef<T>
|
||||||
|
export function computed<T>(
|
||||||
|
options: WritableComputedOptions<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
): WritableComputedRef<T>
|
): WritableComputedRef<T>
|
||||||
export function computed<T>(
|
export function computed<T>(
|
||||||
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
|
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
) {
|
) {
|
||||||
let getter: ComputedGetter<T>
|
let getter: ComputedGetter<T>
|
||||||
let setter: ComputedSetter<T>
|
let setter: ComputedSetter<T>
|
||||||
@ -123,9 +128,16 @@ export function computed<T>(
|
|||||||
setter = getterOrOptions.set
|
setter = getterOrOptions.set
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ComputedRefImpl(
|
const cRef = new ComputedRefImpl(
|
||||||
getter,
|
getter,
|
||||||
setter,
|
setter,
|
||||||
isFunction(getterOrOptions) || !getterOrOptions.set
|
isFunction(getterOrOptions) || !getterOrOptions.set
|
||||||
) as any
|
)
|
||||||
|
|
||||||
|
if (__DEV__ && debugOptions) {
|
||||||
|
cRef.effect.onTrack = debugOptions.onTrack
|
||||||
|
cRef.effect.onTrigger = debugOptions.onTrigger
|
||||||
|
}
|
||||||
|
|
||||||
|
return cRef as any
|
||||||
}
|
}
|
||||||
|
@ -124,14 +124,17 @@ function cleanupEffect(effect: ReactiveEffect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReactiveEffectOptions {
|
export interface DebuggerOptions {
|
||||||
|
onTrack?: (event: DebuggerEvent) => void
|
||||||
|
onTrigger?: (event: DebuggerEvent) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReactiveEffectOptions extends DebuggerOptions {
|
||||||
lazy?: boolean
|
lazy?: boolean
|
||||||
scheduler?: EffectScheduler
|
scheduler?: EffectScheduler
|
||||||
scope?: EffectScope
|
scope?: EffectScope
|
||||||
allowRecurse?: boolean
|
allowRecurse?: boolean
|
||||||
onStop?: () => void
|
onStop?: () => void
|
||||||
onTrack?: (event: DebuggerEvent) => void
|
|
||||||
onTrigger?: (event: DebuggerEvent) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReactiveEffectRunner<T = any> {
|
export interface ReactiveEffectRunner<T = any> {
|
||||||
|
@ -50,6 +50,7 @@ export {
|
|||||||
ReactiveEffectRunner,
|
ReactiveEffectRunner,
|
||||||
ReactiveEffectOptions,
|
ReactiveEffectOptions,
|
||||||
EffectScheduler,
|
EffectScheduler,
|
||||||
|
DebuggerOptions,
|
||||||
DebuggerEvent
|
DebuggerEvent
|
||||||
} from './effect'
|
} from './effect'
|
||||||
export {
|
export {
|
||||||
|
Loading…
Reference in New Issue
Block a user