From: Dmitry Sharshakov Date: Tue, 4 Feb 2020 15:15:27 +0000 (+0300) Subject: feat(reactivity): add shallowReactive function (#689) X-Git-Tag: v3.0.0-alpha.5~118 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7f38c1e0ff5a7591f67ed21aa3a2944db2e72a27;p=thirdparty%2Fvuejs%2Fcore.git feat(reactivity): add shallowReactive function (#689) --- diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index 9db682f897..1b18dc8055 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -1,5 +1,11 @@ import { ref, isRef } from '../src/ref' -import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive' +import { + reactive, + isReactive, + toRaw, + markNonReactive, + shallowReactive +} from '../src/reactive' import { mockWarn } from '@vue/shared' import { computed } from '../src/computed' @@ -212,4 +218,17 @@ describe('reactivity/reactive', () => { expect(isReactive(obj.foo)).toBe(true) expect(isReactive(obj.bar)).toBe(false) }) + + describe('shallowReactive', () => { + test('should not make non-reactive properties reactive', () => { + const props = shallowReactive({ n: { foo: 1 } }) + expect(isReactive(props.n)).toBe(false) + }) + + test('should keep reactive properties reactive', () => { + const props: any = shallowReactive({ n: reactive({ foo: 1 }) }) + props.n = reactive({ foo: 2 }) + expect(isReactive(props.n)).toBe(true) + }) + }) }) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 1b8a61150f..43b6df903b 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -12,6 +12,7 @@ const builtInSymbols = new Set( ) const get = /*#__PURE__*/ createGetter() +const shallowReactiveGet = /*#__PURE__*/ createGetter(false, true) const readonlyGet = /*#__PURE__*/ createGetter(true) const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true) @@ -54,6 +55,7 @@ function createGetter(isReadonly = false, shallow = false) { } const set = /*#__PURE__*/ createSetter() +const shallowReactiveSet = /*#__PURE__*/ createSetter(false, true) const readonlySet = /*#__PURE__*/ createSetter(true) const shallowReadonlySet = /*#__PURE__*/ createSetter(true, true) @@ -165,6 +167,12 @@ export const readonlyHandlers: ProxyHandler = { } } +export const shallowReactiveHandlers: ProxyHandler = { + ...mutableHandlers, + get: shallowReactiveGet, + set: shallowReactiveSet +} + // Props handlers are special in the sense that it should not unwrap top-level // refs (in order to allow refs to be explicitly passed down), but should // retain the reactivity of the normal readonly object. diff --git a/packages/reactivity/src/index.ts b/packages/reactivity/src/index.ts index 05ad6594a9..80e9e62270 100644 --- a/packages/reactivity/src/index.ts +++ b/packages/reactivity/src/index.ts @@ -2,6 +2,7 @@ export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref' export { reactive, isReactive, + shallowReactive, readonly, isReadonly, shallowReadonly, diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index 971ddb6743..f97a1e6f2d 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -2,7 +2,8 @@ import { isObject, toRawType } from '@vue/shared' import { mutableHandlers, readonlyHandlers, - shallowReadonlyHandlers + shallowReadonlyHandlers, + shallowReactiveHandlers } from './baseHandlers' import { mutableCollectionHandlers, @@ -75,7 +76,6 @@ export function readonly( ) } -// @internal // Return a reactive-copy of the original object, where only the root level // properties are readonly, and does NOT unwrap refs nor recursively convert // returned properties. @@ -92,6 +92,19 @@ export function shallowReadonly( ) } +// Return a reactive-copy of the original object, where only the root level +// properties are reactive, and does NOT unwrap refs nor recursively convert +// returned properties. +export function shallowReactive(target: T): T { + return createReactiveObject( + target, + rawToReactive, + reactiveToRaw, + shallowReactiveHandlers, + mutableCollectionHandlers + ) +} + function createReactiveObject( target: unknown, toProxy: WeakMap,