在官网均可找到解决方案
单向数据流
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。
另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告:
export default {
props: ['foo'],
created() {
// ❌ 警告!prop 是只读的!
this.foo = 'bar'
}
}
导致你想要更改一个 prop 的需求通常来源于以下两种场景:
-
prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:
export default {
props: ['initialCounter'],
data() {
return {
// 计数器只是将 this.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
counter: this.initialCounter
}
}
}
2. 需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性:
export default {
props: ['size'],
computed: {
// 该 prop 变更时计算属性也会自动更新
normalizedSize() {
return this.size.trim().toLowerCase()
}
}
}
另一种在组件内实现 v-model
的方式是使用一个可写的,同时具有 getter 和 setter 的计算属性。get
方法需返回 modelValue
prop,而 set
方法需触发相应的事件:
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
computed: {
value: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
}
}
}
}
</script>
<template>
<input v-model="value" />
</template>