feat(reactivity): expose unref and shallowRef
This commit is contained in:
parent
0c67201942
commit
e9024bf1b7
@ -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 { computed } from '@vue/runtime-dom'
|
||||||
|
import { shallowRef, unref } from '../src/ref'
|
||||||
|
|
||||||
describe('reactivity/ref', () => {
|
describe('reactivity/ref', () => {
|
||||||
it('should hold a value', () => {
|
it('should hold a value', () => {
|
||||||
@ -129,6 +138,26 @@ describe('reactivity/ref', () => {
|
|||||||
expect(tupleRef.value[4].value).toBe(1)
|
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', () => {
|
test('isRef', () => {
|
||||||
expect(isRef(ref(1))).toBe(true)
|
expect(isRef(ref(1))).toBe(true)
|
||||||
expect(isRef(computed(() => 1))).toBe(true)
|
expect(isRef(computed(() => 1))).toBe(true)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
|
export { ref, unref, shallowRef, isRef, toRefs, Ref, UnwrapRef } from './ref'
|
||||||
export {
|
export {
|
||||||
reactive,
|
reactive,
|
||||||
isReactive,
|
isReactive,
|
||||||
|
@ -31,10 +31,22 @@ export function isRef(r: any): r is Ref {
|
|||||||
export function ref<T>(value: T): T extends Ref ? T : Ref<T>
|
export function ref<T>(value: T): T extends Ref ? T : Ref<T>
|
||||||
export function ref<T = any>(): Ref<T>
|
export function ref<T = any>(): Ref<T>
|
||||||
export function ref(value?: unknown) {
|
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)) {
|
if (isRef(value)) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
value = convert(value)
|
if (!shallow) {
|
||||||
|
value = convert(value)
|
||||||
|
}
|
||||||
const r = {
|
const r = {
|
||||||
_isRef: true,
|
_isRef: true,
|
||||||
get value() {
|
get value() {
|
||||||
@ -42,7 +54,7 @@ export function ref(value?: unknown) {
|
|||||||
return value
|
return value
|
||||||
},
|
},
|
||||||
set value(newVal) {
|
set value(newVal) {
|
||||||
value = convert(newVal)
|
value = shallow ? newVal : convert(newVal)
|
||||||
trigger(
|
trigger(
|
||||||
r,
|
r,
|
||||||
TriggerOpTypes.SET,
|
TriggerOpTypes.SET,
|
||||||
@ -54,6 +66,10 @@ export function ref(value?: unknown) {
|
|||||||
return r
|
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>(
|
export function toRefs<T extends object>(
|
||||||
object: T
|
object: T
|
||||||
): { [K in keyof T]: Ref<T[K]> } {
|
): { [K in keyof T]: Ref<T[K]> } {
|
||||||
|
@ -13,7 +13,8 @@ import {
|
|||||||
isRef,
|
isRef,
|
||||||
isReactive,
|
isReactive,
|
||||||
Ref,
|
Ref,
|
||||||
ComputedRef
|
ComputedRef,
|
||||||
|
unref
|
||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { Slots } from './componentSlots'
|
import { Slots } from './componentSlots'
|
||||||
@ -84,8 +85,6 @@ const enum AccessTypes {
|
|||||||
OTHER
|
OTHER
|
||||||
}
|
}
|
||||||
|
|
||||||
const unwrapRef = (val: unknown) => (isRef(val) ? val.value : val)
|
|
||||||
|
|
||||||
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
||||||
get(target: ComponentInternalInstance, key: string) {
|
get(target: ComponentInternalInstance, key: string) {
|
||||||
// fast path for unscopables when using `with` block
|
// fast path for unscopables when using `with` block
|
||||||
@ -115,7 +114,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
case AccessTypes.DATA:
|
case AccessTypes.DATA:
|
||||||
return data[key]
|
return data[key]
|
||||||
case AccessTypes.CONTEXT:
|
case AccessTypes.CONTEXT:
|
||||||
return unwrapRef(renderContext[key])
|
return unref(renderContext[key])
|
||||||
case AccessTypes.PROPS:
|
case AccessTypes.PROPS:
|
||||||
return propsProxy![key]
|
return propsProxy![key]
|
||||||
// default: just fallthrough
|
// default: just fallthrough
|
||||||
@ -125,7 +124,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
return data[key]
|
return data[key]
|
||||||
} else if (hasOwn(renderContext, key)) {
|
} else if (hasOwn(renderContext, key)) {
|
||||||
accessCache![key] = AccessTypes.CONTEXT
|
accessCache![key] = AccessTypes.CONTEXT
|
||||||
return unwrapRef(renderContext[key])
|
return unref(renderContext[key])
|
||||||
} else if (type.props != null) {
|
} else if (type.props != null) {
|
||||||
// only cache other properties when instance has declared (this stable)
|
// only cache other properties when instance has declared (this stable)
|
||||||
// props
|
// props
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
export const version = __VERSION__
|
export const version = __VERSION__
|
||||||
export {
|
export {
|
||||||
ref,
|
ref,
|
||||||
|
unref,
|
||||||
|
shallowRef,
|
||||||
isRef,
|
isRef,
|
||||||
toRefs,
|
toRefs,
|
||||||
reactive,
|
reactive,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { expectType } from 'tsd'
|
import { expectType } from 'tsd'
|
||||||
import { Ref, ref } from './index'
|
import { Ref, ref, isRef, unref } from './index'
|
||||||
import { isRef } from '@vue/reactivity'
|
|
||||||
|
|
||||||
function foo(arg: number | Ref<number>) {
|
function foo(arg: number | Ref<number>) {
|
||||||
// ref coercing
|
// ref coercing
|
||||||
@ -11,6 +10,9 @@ function foo(arg: number | Ref<number>) {
|
|||||||
if (isRef(arg)) {
|
if (isRef(arg)) {
|
||||||
expectType<Ref<number>>(arg)
|
expectType<Ref<number>>(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ref unwrapping
|
||||||
|
expectType<number>(unref(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
foo(1)
|
foo(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user