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)
})
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)
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'
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() {
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