Skip to content

Commit

Permalink
feat(reactivity): expose unref and shallowRef
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Feb 22, 2020
1 parent 0c67201 commit e9024bf
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
31 changes: 30 additions & 1 deletion packages/reactivity/__tests__/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { ref, effect, reactive, isRef, toRefs, Ref } from '../src/index'
import {
ref,
effect,
reactive,
isRef,
toRefs,
Ref,
isReactive
} from '../src/index'
import { computed } from '@vue/runtime-dom'
import { shallowRef, unref } from '../src/ref'

describe('reactivity/ref', () => {
it('should hold a value', () => {
Expand Down Expand Up @@ -129,6 +138,26 @@ describe('reactivity/ref', () => {
expect(tupleRef.value[4].value).toBe(1)
})

test('unref', () => {
expect(unref(1)).toBe(1)
expect(unref(ref(1))).toBe(1)
})

test('shallowRef', () => {
const sref = shallowRef({ a: 1 })
expect(isReactive(sref.value)).toBe(false)

let dummy
effect(() => {
dummy = sref.value.a
})
expect(dummy).toBe(1)

sref.value = { a: 2 }
expect(isReactive(sref.value)).toBe(false)
expect(dummy).toBe(2)
})

test('isRef', () => {
expect(isRef(ref(1))).toBe(true)
expect(isRef(computed(() => 1))).toBe(true)
Expand Down
2 changes: 1 addition & 1 deletion packages/reactivity/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
export { ref, unref, shallowRef, isRef, toRefs, Ref, UnwrapRef } from './ref'
export {
reactive,
isReactive,
Expand Down
20 changes: 18 additions & 2 deletions packages/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,30 @@ export function isRef(r: any): r is Ref {
export function ref<T>(value: T): T extends Ref ? T : Ref<T>
export function ref<T = any>(): Ref<T>
export function ref(value?: unknown) {
return createRef(value)
}

export function shallowRef<T>(value: T): T extends Ref ? T : Ref<T>
export function shallowRef<T = any>(): Ref<T>
export function shallowRef(value?: unknown) {
return createRef(value, true)
}

function createRef(value: unknown, shallow = false) {
if (isRef(value)) {
return value
}
value = convert(value)
if (!shallow) {
value = convert(value)
}
const r = {
_isRef: true,
get value() {
track(r, TrackOpTypes.GET, 'value')
return value
},
set value(newVal) {
value = convert(newVal)
value = shallow ? newVal : convert(newVal)
trigger(
r,
TriggerOpTypes.SET,
Expand All @@ -54,6 +66,10 @@ export function ref(value?: unknown) {
return r
}

export function unref<T>(ref: T): T extends Ref<infer V> ? V : T {
return isRef(ref) ? (ref.value as any) : ref
}

export function toRefs<T extends object>(
object: T
): { [K in keyof T]: Ref<T[K]> } {
Expand Down
9 changes: 4 additions & 5 deletions packages/runtime-core/src/componentProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
isRef,
isReactive,
Ref,
ComputedRef
ComputedRef,
unref
} from '@vue/reactivity'
import { warn } from './warning'
import { Slots } from './componentSlots'
Expand Down Expand Up @@ -84,8 +85,6 @@ const enum AccessTypes {
OTHER
}

const unwrapRef = (val: unknown) => (isRef(val) ? val.value : val)

export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
get(target: ComponentInternalInstance, key: string) {
// fast path for unscopables when using `with` block
Expand Down Expand Up @@ -115,7 +114,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
case AccessTypes.DATA:
return data[key]
case AccessTypes.CONTEXT:
return unwrapRef(renderContext[key])
return unref(renderContext[key])
case AccessTypes.PROPS:
return propsProxy![key]
// default: just fallthrough
Expand All @@ -125,7 +124,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
return data[key]
} else if (hasOwn(renderContext, key)) {
accessCache![key] = AccessTypes.CONTEXT
return unwrapRef(renderContext[key])
return unref(renderContext[key])
} else if (type.props != null) {
// only cache other properties when instance has declared (this stable)
// props
Expand Down
2 changes: 2 additions & 0 deletions packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
export const version = __VERSION__
export {
ref,
unref,
shallowRef,
isRef,
toRefs,
reactive,
Expand Down
6 changes: 4 additions & 2 deletions test-dts/ref.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { expectType } from 'tsd'
import { Ref, ref } from './index'
import { isRef } from '@vue/reactivity'
import { Ref, ref, isRef, unref } from './index'

function foo(arg: number | Ref<number>) {
// ref coercing
Expand All @@ -11,6 +10,9 @@ function foo(arg: number | Ref<number>) {
if (isRef(arg)) {
expectType<Ref<number>>(arg)
}

// ref unwrapping
expectType<number>(unref(arg))
}

foo(1)

0 comments on commit e9024bf

Please sign in to comment.