fix(setup): setup props should pass isReactive check

close #12561
This commit is contained in:
Evan You 2022-06-20 13:09:56 +08:00
parent 2533a360a8
commit 52cf912d85
3 changed files with 28 additions and 4 deletions

View File

@ -30,7 +30,7 @@ import {
isFunction
} from '../util/index'
import type { Component } from 'types/component'
import { TrackOpTypes } from '../../v3'
import { shallowReactive, TrackOpTypes } from 'v3'
const sharedPropertyDefinition = {
enumerable: true,
@ -71,7 +71,7 @@ export function initState(vm: Component) {
function initProps(vm: Component, propsOptions: Object) {
const propsData = vm.$options.propsData || {}
const props = (vm._props = {})
const props = (vm._props = shallowReactive({}))
// cache prop keys so that future props updates can iterate using Array
// instead of dynamic object key enumeration.
const keys: string[] = (vm.$options._propKeys = [])

View File

@ -1,5 +1,6 @@
import { Component } from 'types/component'
import { PropOptions } from 'types/options'
import { toggleObserving } from '../core/observer'
import { def, invokeWithErrorHandling, isReserved, warn } from '../core/util'
import VNode from '../core/vdom/vnode'
import {
@ -10,6 +11,7 @@ import {
isObject
} from '../shared/util'
import { currentInstance, setCurrentInstance } from './currentInstance'
import { shallowReactive } from './reactivity/reactive'
import { isRef } from './reactivity/ref'
/**
@ -29,13 +31,15 @@ export function initSetup(vm: Component) {
const ctx = (vm._setupContext = createSetupContext(vm))
setCurrentInstance(vm)
toggleObserving(false)
const setupResult = invokeWithErrorHandling(
setup,
null,
[vm._props, ctx],
[vm._props || shallowReactive({}), ctx],
vm,
`setup`
)
toggleObserving(true)
setCurrentInstance()
if (isFunction(setupResult)) {

View File

@ -1,4 +1,4 @@
import { h, ref, reactive } from 'v3'
import { h, ref, reactive, isReactive, toRef, isRef } from 'v3'
import { nextTick } from 'core/util'
import { effect } from 'v3/reactivity/effect'
import Vue from 'vue'
@ -247,4 +247,24 @@ describe('api: setup context', () => {
}).$mount()
expect(spy).toHaveBeenCalled()
})
// #12561
it.only('setup props should be reactive', () => {
const msg = ref('hi')
const Child = {
props: ['msg'],
setup: props => {
expect(isReactive(props)).toBe(true)
expect(isRef(toRef(props, 'foo'))).toBe(true)
return () => {}
}
}
new Vue({
setup() {
return h => h(Child, { props: { msg } })
}
}).$mount()
})
})