From a8686bbf6f0e97f9b06917dcd35415bcfb924acc Mon Sep 17 00:00:00 2001 From: shaonialife <1763175154@qq.com> Date: Sun, 5 Jul 2020 16:23:55 +0800 Subject: [PATCH] feat: add customRef (#423) --- src/apis/state.ts | 1 + src/reactivity/index.ts | 1 + src/reactivity/ref.ts | 20 +++++++++++ test/v3/reactivity/ref.spec.ts | 64 ++++++++++++++++++---------------- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/apis/state.ts b/src/apis/state.ts index 6fdb5cc7..772406f5 100644 --- a/src/apis/state.ts +++ b/src/apis/state.ts @@ -5,6 +5,7 @@ export { markReactive, reactive, ref, + customRef, Ref, set, shallowReactive, diff --git a/src/reactivity/index.ts b/src/reactivity/index.ts index 5de8bc2e..115ee971 100644 --- a/src/reactivity/index.ts +++ b/src/reactivity/index.ts @@ -9,6 +9,7 @@ export { } from './reactive' export { ref, + customRef, isRef, Ref, createRef, diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts index fbe78b4a..577e736e 100644 --- a/src/reactivity/ref.ts +++ b/src/reactivity/ref.ts @@ -128,6 +128,26 @@ export function toRefs(obj: T): ToRefs { return ret } +export type CustomRefFactory = ( + track: () => void, + trigger: () => void +) => { + get: () => T + set: (value: T) => void +} + +export function customRef(factory: CustomRefFactory): Ref { + const version = ref(0) + return createRef( + factory( + () => void version.value, + () => { + ++version.value + } + ) + ) +} + export function toRef( object: T, key: K diff --git a/test/v3/reactivity/ref.spec.ts b/test/v3/reactivity/ref.spec.ts index 6abeb985..68062244 100644 --- a/test/v3/reactivity/ref.spec.ts +++ b/test/v3/reactivity/ref.spec.ts @@ -1,5 +1,6 @@ import { ref, + customRef, reactive, isRef, toRef, @@ -308,34 +309,37 @@ describe('reactivity/ref', () => { expect(dummyY).toBe(5) }) - // test('customRef', () => { - // let value = 1; - // let _trigger: () => void; - - // const custom = customRef((track, trigger) => ({ - // get() { - // track(); - // return value; - // }, - // set(newValue: number) { - // value = newValue; - // _trigger = trigger; - // }, - // })); - - // expect(isRef(custom)).toBe(true); - - // let dummy; - // watchEffect(() => { - // dummy = custom.value; - // }, {flush: 'sync'}); - // expect(dummy).toBe(1); - - // custom.value = 2; - // // should not trigger yet - // expect(dummy).toBe(1); - - // _trigger!(); - // expect(dummy).toBe(2); - // }); + test('customRef', () => { + let value = 1 + let _trigger: () => void + + const custom = customRef((track, trigger) => ({ + get() { + track() + return value + }, + set(newValue: number) { + value = newValue + _trigger = trigger + }, + })) + + expect(isRef(custom)).toBe(true) + + let dummy + watchEffect( + () => { + dummy = custom.value + }, + { flush: 'sync' } + ) + expect(dummy).toBe(1) + + custom.value = 2 + // should not trigger yet + expect(dummy).toBe(1) + + _trigger!() + expect(dummy).toBe(2) + }) })