perf(reactivity): ref should not trigger if value did not change
Note: shallowRef will always trigger on assignment because it does not account for deep mutations close #1012
This commit is contained in:
		
							parent
							
								
									7d858a9001
								
							
						
					
					
						commit
						b0d4df9743
					
				@ -22,11 +22,19 @@ describe('reactivity/ref', () => {
 | 
				
			|||||||
  it('should be reactive', () => {
 | 
					  it('should be reactive', () => {
 | 
				
			||||||
    const a = ref(1)
 | 
					    const a = ref(1)
 | 
				
			||||||
    let dummy
 | 
					    let dummy
 | 
				
			||||||
 | 
					    let calls = 0
 | 
				
			||||||
    effect(() => {
 | 
					    effect(() => {
 | 
				
			||||||
 | 
					      calls++
 | 
				
			||||||
      dummy = a.value
 | 
					      dummy = a.value
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    expect(calls).toBe(1)
 | 
				
			||||||
    expect(dummy).toBe(1)
 | 
					    expect(dummy).toBe(1)
 | 
				
			||||||
    a.value = 2
 | 
					    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)
 | 
					    expect(dummy).toBe(2)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -174,6 +182,22 @@ describe('reactivity/ref', () => {
 | 
				
			|||||||
    expect(dummy).toBe(2)
 | 
					    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', () => {
 | 
					  test('isRef', () => {
 | 
				
			||||||
    expect(isRef(ref(1))).toBe(true)
 | 
					    expect(isRef(ref(1))).toBe(true)
 | 
				
			||||||
    expect(isRef(computed(() => 1))).toBe(true)
 | 
					    expect(isRef(computed(() => 1))).toBe(true)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { track, trigger } from './effect'
 | 
					import { track, trigger } from './effect'
 | 
				
			||||||
import { TrackOpTypes, TriggerOpTypes } from './operations'
 | 
					import { TrackOpTypes, TriggerOpTypes } from './operations'
 | 
				
			||||||
import { isObject } from '@vue/shared'
 | 
					import { isObject, hasChanged } from '@vue/shared'
 | 
				
			||||||
import { reactive, isProxy } from './reactive'
 | 
					import { reactive, isProxy, toRaw } from './reactive'
 | 
				
			||||||
import { ComputedRef } from './computed'
 | 
					import { ComputedRef } from './computed'
 | 
				
			||||||
import { CollectionTypes } from './collectionHandlers'
 | 
					import { CollectionTypes } from './collectionHandlers'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,13 +43,11 @@ export function shallowRef(value?: unknown) {
 | 
				
			|||||||
  return createRef(value, true)
 | 
					  return createRef(value, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createRef(value: unknown, shallow = false) {
 | 
					function createRef(rawValue: unknown, shallow = false) {
 | 
				
			||||||
  if (isRef(value)) {
 | 
					  if (isRef(rawValue)) {
 | 
				
			||||||
    return value
 | 
					    return rawValue
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (!shallow) {
 | 
					 | 
				
			||||||
    value = convert(value)
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  let value = shallow ? rawValue : convert(rawValue)
 | 
				
			||||||
  const r = {
 | 
					  const r = {
 | 
				
			||||||
    _isRef: true,
 | 
					    _isRef: true,
 | 
				
			||||||
    get value() {
 | 
					    get value() {
 | 
				
			||||||
@ -57,13 +55,16 @@ function createRef(value: unknown, shallow = false) {
 | 
				
			|||||||
      return value
 | 
					      return value
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    set value(newVal) {
 | 
					    set value(newVal) {
 | 
				
			||||||
      value = shallow ? newVal : convert(newVal)
 | 
					      if (shallow || hasChanged(toRaw(newVal), rawValue)) {
 | 
				
			||||||
      trigger(
 | 
					        rawValue = newVal
 | 
				
			||||||
        r,
 | 
					        value = shallow ? newVal : convert(newVal)
 | 
				
			||||||
        TriggerOpTypes.SET,
 | 
					        trigger(
 | 
				
			||||||
        'value',
 | 
					          r,
 | 
				
			||||||
        __DEV__ ? { newValue: newVal } : void 0
 | 
					          TriggerOpTypes.SET,
 | 
				
			||||||
      )
 | 
					          'value',
 | 
				
			||||||
 | 
					          __DEV__ ? { newValue: newVal } : void 0
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return r
 | 
					  return r
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user