fix(props): should not unwrap props that are raw refs

close #12930
This commit is contained in:
Evan You 2023-12-06 15:10:49 +08:00
parent 947993f7e8
commit 08382f0080
2 changed files with 36 additions and 12 deletions

View File

@ -95,19 +95,25 @@ function initProps(vm: Component, propsOptions: Object) {
vm vm
) )
} }
defineReactive(props, key, value, () => { defineReactive(
if (!isRoot && !isUpdatingChildComponent) { props,
warn( key,
`Avoid mutating a prop directly since the value will be ` + value,
`overwritten whenever the parent component re-renders. ` + () => {
`Instead, use a data or computed property based on the prop's ` + if (!isRoot && !isUpdatingChildComponent) {
`value. Prop being mutated: "${key}"`, warn(
vm `Avoid mutating a prop directly since the value will be ` +
) `overwritten whenever the parent component re-renders. ` +
} `Instead, use a data or computed property based on the prop's ` +
}) `value. Prop being mutated: "${key}"`,
vm
)
}
},
true
)
} else { } else {
defineReactive(props, key, value) defineReactive(props, key, value, undefined, true)
} }
// static props are already proxied on the component's prototype // static props are already proxied on the component's prototype
// during Vue.extend(). We only need to proxy props defined at // during Vue.extend(). We only need to proxy props defined at

View File

@ -1,6 +1,7 @@
import Vue from 'vue' import Vue from 'vue'
import { hasSymbol } from 'core/util/env' import { hasSymbol } from 'core/util/env'
import testObjectOption from '../../../helpers/test-object-option' import testObjectOption from '../../../helpers/test-object-option'
import { ref } from 'v3'
describe('Options props', () => { describe('Options props', () => {
testObjectOption('props') testObjectOption('props')
@ -593,4 +594,21 @@ describe('Options props', () => {
'Invalid prop type: "String" is not a constructor' 'Invalid prop type: "String" is not a constructor'
).toHaveBeenWarned() ).toHaveBeenWarned()
}) })
// #12930
it('should not unwrap prop values that are raw refs', () => {
let val
const Comp = {
props: ['msg'],
created() {
val = this.msg
},
render() {}
}
const r = ref()
new Vue({
render: h => h(Comp, { props: { msg: r }})
}).$mount()
expect(val).toBe(r)
})
}) })