Skip to content

Commit b83c580

Browse files
committed
feat(reactivity): add support for customRef API
1 parent 4046f0b commit b83c580

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

packages/reactivity/__tests__/ref.spec.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
isReactive
99
} from '../src/index'
1010
import { computed } from '@vue/runtime-dom'
11-
import { shallowRef, unref } from '../src/ref'
11+
import { shallowRef, unref, customRef } from '../src/ref'
1212

1313
describe('reactivity/ref', () => {
1414
it('should hold a value', () => {
@@ -208,4 +208,33 @@ describe('reactivity/ref', () => {
208208
expect(dummyX).toBe(4)
209209
expect(dummyY).toBe(5)
210210
})
211+
212+
test('customRef', () => {
213+
let value = 1
214+
let _trigger: () => void
215+
216+
const custom = customRef((track, trigger) => ({
217+
get() {
218+
track()
219+
return value
220+
},
221+
set(newValue: number) {
222+
value = newValue
223+
_trigger = trigger
224+
}
225+
}))
226+
227+
let dummy
228+
effect(() => {
229+
dummy = custom.value
230+
})
231+
expect(dummy).toBe(1)
232+
233+
custom.value = 2
234+
// should not trigger yet
235+
expect(dummy).toBe(1)
236+
237+
_trigger!()
238+
expect(dummy).toBe(2)
239+
})
211240
})

packages/reactivity/src/index.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
export { ref, unref, shallowRef, isRef, toRefs, Ref, UnwrapRef } from './ref'
1+
export {
2+
ref,
3+
unref,
4+
shallowRef,
5+
isRef,
6+
toRefs,
7+
customRef,
8+
Ref,
9+
UnwrapRef
10+
} from './ref'
211
export {
312
reactive,
413
isReactive,

packages/reactivity/src/ref.ts

+25
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,31 @@ export function unref<T>(ref: T): T extends Ref<infer V> ? V : T {
7070
return isRef(ref) ? (ref.value as any) : ref
7171
}
7272

73+
export type CustomRefFactory<T> = (
74+
track: () => void,
75+
trigger: () => void
76+
) => {
77+
get: () => T
78+
set: (value: T) => void
79+
}
80+
81+
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
82+
const { get, set } = factory(
83+
() => track(r, TrackOpTypes.GET, 'value'),
84+
() => trigger(r, TriggerOpTypes.SET, 'value')
85+
)
86+
const r = {
87+
_isRef: true,
88+
get value() {
89+
return get()
90+
},
91+
set value(v) {
92+
set(v)
93+
}
94+
}
95+
return r as any
96+
}
97+
7398
export function toRefs<T extends object>(
7499
object: T
75100
): { [K in keyof T]: Ref<T[K]> } {

packages/runtime-core/src/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ export {
77
shallowRef,
88
isRef,
99
toRefs,
10+
customRef,
1011
reactive,
1112
isReactive,
1213
readonly,
1314
isReadonly,
1415
shallowReactive,
15-
toRaw,
16-
markNonReactive
16+
markNonReactive,
17+
toRaw
1718
} from '@vue/reactivity'
1819
export { computed } from './apiComputed'
1920
export { watch, watchEffect } from './apiWatch'

0 commit comments

Comments
 (0)