-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', () => {
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)
-export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
+export { ref, unref, shallowRef, isRef, toRefs, Ref, UnwrapRef } from './ref'
export {
reactive,
isReactive,
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() {
return value
},
set value(newVal) {
- value = convert(newVal)
+ value = shallow ? newVal : convert(newVal)
trigger(
r,
TriggerOpTypes.SET,
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]> } {
isRef,
isReactive,
Ref,
- ComputedRef
+ ComputedRef,
+ unref
} from '@vue/reactivity'
import { warn } from './warning'
import { Slots } from './componentSlots'
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
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
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
export const version = __VERSION__
export {
ref,
+ unref,
+ shallowRef,
isRef,
toRefs,
reactive,
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
if (isRef(arg)) {
expectType<Ref<number>>(arg)
}
+
+ // ref unwrapping
+ expectType<number>(unref(arg))
}
foo(1)