]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
perf(reactivity): ref should not trigger if value did not change
authorEvan You <yyx990803@gmail.com>
Wed, 22 Apr 2020 19:11:01 +0000 (15:11 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 22 Apr 2020 19:11:01 +0000 (15:11 -0400)
Note: shallowRef will always trigger on assignment because it does not
account for deep mutations

close #1012

packages/reactivity/__tests__/ref.spec.ts
packages/reactivity/src/ref.ts

index 7885ff7d0c881af59cad7a813d05750d54210efa..f6fc7f2319a64e2c961cfa23817829e613336c2f 100644 (file)
@@ -22,11 +22,19 @@ describe('reactivity/ref', () => {
   it('should be reactive', () => {
     const a = ref(1)
     let dummy
+    let calls = 0
     effect(() => {
+      calls++
       dummy = a.value
     })
+    expect(calls).toBe(1)
     expect(dummy).toBe(1)
     a.value = 2
+    expect(calls).toBe(2)
+    expect(dummy).toBe(2)
+    // same value should not trigger
+    a.value = 2
+    expect(calls).toBe(2)
     expect(dummy).toBe(2)
   })
 
@@ -174,6 +182,22 @@ describe('reactivity/ref', () => {
     expect(dummy).toBe(2)
   })
 
+  test('shallowRef force trigger', () => {
+    const sref = shallowRef({ a: 1 })
+    let dummy
+    effect(() => {
+      dummy = sref.value.a
+    })
+    expect(dummy).toBe(1)
+
+    sref.value.a = 2
+    expect(dummy).toBe(1) // should not trigger yet
+
+    // force trigger
+    sref.value = sref.value
+    expect(dummy).toBe(2)
+  })
+
   test('isRef', () => {
     expect(isRef(ref(1))).toBe(true)
     expect(isRef(computed(() => 1))).toBe(true)
index 79c2dc52c2ab741061bdc0ea368b71497a91fe20..59badad4d56a1c4869a81c287a6e56c98f08b8ba 100644 (file)
@@ -1,7 +1,7 @@
 import { track, trigger } from './effect'
 import { TrackOpTypes, TriggerOpTypes } from './operations'
-import { isObject } from '@vue/shared'
-import { reactive, isProxy } from './reactive'
+import { isObject, hasChanged } from '@vue/shared'
+import { reactive, isProxy, toRaw } from './reactive'
 import { ComputedRef } from './computed'
 import { CollectionTypes } from './collectionHandlers'
 
@@ -43,13 +43,11 @@ export function shallowRef(value?: unknown) {
   return createRef(value, true)
 }
 
-function createRef(value: unknown, shallow = false) {
-  if (isRef(value)) {
-    return value
-  }
-  if (!shallow) {
-    value = convert(value)
+function createRef(rawValue: unknown, shallow = false) {
+  if (isRef(rawValue)) {
+    return rawValue
   }
+  let value = shallow ? rawValue : convert(rawValue)
   const r = {
     _isRef: true,
     get value() {
@@ -57,13 +55,16 @@ function createRef(value: unknown, shallow = false) {
       return value
     },
     set value(newVal) {
-      value = shallow ? newVal : convert(newVal)
-      trigger(
-        r,
-        TriggerOpTypes.SET,
-        'value',
-        __DEV__ ? { newValue: newVal } : void 0
-      )
+      if (shallow || hasChanged(toRaw(newVal), rawValue)) {
+        rawValue = newVal
+        value = shallow ? newVal : convert(newVal)
+        trigger(
+          r,
+          TriggerOpTypes.SET,
+          'value',
+          __DEV__ ? { newValue: newVal } : void 0
+        )
+      }
     }
   }
   return r