Skip to content

Commit

Permalink
feat(reactivity): proxyRefs method and ShallowUnwrapRefs type (#1682
Browse files Browse the repository at this point in the history
)

* feat(reactivity): `proxyRefs` method and `ShallowUnwrapRefs` type

BREAKING CHANGE: template auto ref unwrapping are now applied shallowly,
i.e. only at the root level. See #1682 for
more details.
  • Loading branch information
yyx990803 authored Jul 28, 2020
1 parent de62cc0 commit aa06b10
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 10 deletions.
6 changes: 4 additions & 2 deletions packages/reactivity/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
export {
ref,
unref,
shallowRef,
isRef,
toRef,
toRefs,
unref,
proxyRefs,
customRef,
triggerRef,
Ref,
UnwrapRef,
ToRefs,
UnwrapRef,
ShallowUnwrapRef,
RefUnwrapBailTypes
} from './ref'
export {
Expand Down
27 changes: 26 additions & 1 deletion packages/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { track, trigger } from './effect'
import { TrackOpTypes, TriggerOpTypes } from './operations'
import { isObject, hasChanged } from '@vue/shared'
import { reactive, isProxy, toRaw } from './reactive'
import { reactive, isProxy, toRaw, isReactive } from './reactive'
import { CollectionTypes } from './collectionHandlers'

declare const RefSymbol: unique symbol
Expand Down Expand Up @@ -71,6 +71,27 @@ export function unref<T>(ref: T): T extends Ref<infer V> ? V : T {
return isRef(ref) ? (ref.value as any) : ref
}

const shallowUnwrapHandlers: ProxyHandler<any> = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key]
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value
return true
} else {
return Reflect.set(target, key, value, receiver)
}
}
}

export function proxyRefs<T extends object>(
objectWithRefs: T
): ShallowUnwrapRef<T> {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers)
}

export type CustomRefFactory<T> = (
track: () => void,
trigger: () => void
Expand Down Expand Up @@ -146,6 +167,10 @@ type BaseTypes = string | number | boolean
*/
export interface RefUnwrapBailTypes {}

export type ShallowUnwrapRef<T> = {
[K in keyof T]: T[K] extends Ref<infer V> ? V : T[K]
}

export type UnwrapRef<T> = T extends Ref<infer V>
? UnwrapRefSimple<V>
: UnwrapRefSimple<T>
Expand Down
6 changes: 3 additions & 3 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { VNode, VNodeChild, isVNode } from './vnode'
import {
reactive,
ReactiveEffect,
pauseTracking,
resetTracking,
shallowReadonly
shallowReadonly,
proxyRefs
} from '@vue/reactivity'
import {
CreateComponentPublicInstance,
Expand Down Expand Up @@ -548,7 +548,7 @@ export function handleSetupResult(
}
// setup returned bindings.
// assuming a render function compiled from template is present.
instance.setupState = reactive(setupResult)
instance.setupState = proxyRefs(setupResult)
if (__DEV__) {
exposeSetupStateOnRenderContext(instance)
}
Expand Down
6 changes: 3 additions & 3 deletions packages/runtime-core/src/componentProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
} from '@vue/shared'
import {
ReactiveEffect,
UnwrapRef,
toRaw,
shallowReadonly,
ReactiveFlags,
track,
TrackOpTypes
TrackOpTypes,
ShallowUnwrapRef
} from '@vue/reactivity'
import {
ExtractComputedReturns,
Expand Down Expand Up @@ -154,7 +154,7 @@ export type ComponentPublicInstance<
$nextTick: typeof nextTick
$watch: typeof instanceWatch
} & P &
UnwrapRef<B> &
ShallowUnwrapRef<B> &
D &
ExtractComputedReturns<C> &
M &
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 @@ -8,6 +8,7 @@ export {
readonly,
// utilities
unref,
proxyRefs,
isRef,
toRef,
toRefs,
Expand Down Expand Up @@ -125,6 +126,7 @@ export {
ComputedRef,
WritableComputedRef,
UnwrapRef,
ShallowUnwrapRef,
WritableComputedOptions,
ToRefs,
DeepReadonly
Expand Down
2 changes: 1 addition & 1 deletion test-dts/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ describe('with object props', () => {

// assert setup context unwrapping
expectType<number>(this.c)
expectType<string>(this.d.e)
expectType<string>(this.d.e.value)
expectType<GT>(this.f.g)

// setup context properties should be mutable
Expand Down

0 comments on commit aa06b10

Please sign in to comment.