diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts index 87b0ad77..a7a73a44 100644 --- a/src/reactivity/ref.ts +++ b/src/reactivity/ref.ts @@ -2,6 +2,7 @@ import { RefKey } from '../utils/symbols' import { proxy, isPlainObject, warn, def } from '../utils' import { reactive, isReactive, shallowReactive } from './reactive' import { readonlySet } from '../utils/sets' +import { set } from './set' declare const _refBrand: unique symbol export interface Ref { @@ -154,6 +155,7 @@ export function toRef( object: T, key: K ): Ref { + if (!(key in object)) set(object, key, undefined) const v = object[key] if (isRef(v)) return v diff --git a/test/apis/computed.spec.js b/test/apis/computed.spec.js index af0ce83b..da7c8300 100644 --- a/test/apis/computed.spec.js +++ b/test/apis/computed.spec.js @@ -1,5 +1,12 @@ const Vue = require('vue/dist/vue.common.js') -const { ref, computed, isReadonly, reactive, isRef } = require('../../src') +const { + ref, + computed, + isReadonly, + reactive, + isRef, + toRef, +} = require('../../src') describe('Hooks computed', () => { beforeEach(() => { @@ -195,6 +202,26 @@ describe('Hooks computed', () => { expect(app.$children[1].example).toBe('B') }) + it('should watch a reactive property created via toRef', (done) => { + const spy = jest.fn() + const vm = new Vue({ + setup() { + const a = reactive({}) + const b = toRef(a, 'b') + + return { + a, + b, + } + }, + }) + vm.$watch('b', spy) + vm.b = 2 + waitForUpdate(() => { + expect(spy).toHaveBeenCalledWith(2, undefined) + }).then(done) + }) + it('should be readonly', () => { let a = { a: 1 } const x = computed(() => a)