]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(reactivity): add shallowReactive function (#689)
authorDmitry Sharshakov <d3dx12.xx@gmail.com>
Tue, 4 Feb 2020 15:15:27 +0000 (18:15 +0300)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2020 15:15:27 +0000 (10:15 -0500)
packages/reactivity/__tests__/reactive.spec.ts
packages/reactivity/src/baseHandlers.ts
packages/reactivity/src/index.ts
packages/reactivity/src/reactive.ts

index 9db682f897318e3bc3e9344341327c28f4486d92..1b18dc8055af6894fdea53e8f8010839451d8d58 100644 (file)
@@ -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)
+    })
+  })
 })
index 1b8a61150f5dba261bb7c2e06051d18a32cd355e..43b6df903bdf6448ab368d9718e0a10ebd28fcca 100644 (file)
@@ -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<object> = {
   }
 }
 
+export const shallowReactiveHandlers: ProxyHandler<object> = {
+  ...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.
index 05ad6594a90de10bd53317b4277973c58cb293c1..80e9e622703ba9dcbb01ccc30b1475e3995b548d 100644 (file)
@@ -2,6 +2,7 @@ export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
 export {
   reactive,
   isReactive,
+  shallowReactive,
   readonly,
   isReadonly,
   shallowReadonly,
index 971ddb6743e9d3351d482bc07dfaede7216d65fb..f97a1e6f2d4ef1763b6301862e4a97bd94e5bb8b 100644 (file)
@@ -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<T extends object>(
   )
 }
 
-// @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<T extends object>(
   )
 }
 
+// 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<T extends object>(target: T): T {
+  return createReactiveObject(
+    target,
+    rawToReactive,
+    reactiveToRaw,
+    shallowReactiveHandlers,
+    mutableCollectionHandlers
+  )
+}
+
 function createReactiveObject(
   target: unknown,
   toProxy: WeakMap<any, any>,