Vue组件中的props是否可变?子组件修改props传值相关问题咨询
Vue组件props是否可以直接修改?
你示例中的代码*短期内可以正常运行,但这是Vue官方不推荐的反模式,存在很大的维护隐患。
核心原理
Vue的props设计遵循单向数据流规则:
- 所有props都遵循从上到下的单向绑定,父组件的属性变化会向下同步到子组件,但反向修改不会被允许
- 如果是字符串、数字、布尔值等基础类型的props,直接在子组件修改会直接在控制台抛出报错
- 如果是对象、数组等引用类型的props,因为父子组件共享同一个内存引用,你修改数组的元素属性、调用
push/splice等变异方法时,Vue不会触发报错,但本质还是违反了单向数据流的设计原则
直接修改引用类型props的问题
- 父组件如果触发重新渲染,你在子组件对props做的所有修改都会被直接覆盖
- 状态变更来源不清晰,后续debug时无法快速定位是父组件还是某一个子组件修改了数组数据,项目复杂度上升后维护成本会极高
正确实现方案
标准做法是子组件只负责抛出事件,由持有源数据的父组件执行修改操作,修改后的状态再通过props同步到子组件,具体改法如下:
- 调整子组件的方法,所有修改操作都改为抛出对应事件:
export default { name: 'multi-options', props: ['options'], methods: { updateOption(index, value) { this.$emit('update-option', index, value) }, removeOption(index) { this.$emit('remove-option', index) }, addOption() { this.$emit('add-option') }, updateCorrect(index, value) { this.$emit('update-correct', index, value) } }, }
- 调整模板里的复选框绑定,不要直接用
v-model绑定prop的属性:
<b-form-checkbox :id="`option-${index}`" name="options" class="f-14 text-muted ml-1" :checked="option.correct" @change="updateCorrect(index, $event)" > Correct? </b-form-checkbox>
- 父组件引用子组件时监听对应事件,修改自身的源数据:
<multi-options :options="formOptions" @update-option="(index, val) => formOptions[index].answer = val" @remove-option="index => formOptions.splice(index, 1)" @add-option="() => formOptions.push({answer: '', correct: false})" @update-correct="(index, val) => formOptions[index].correct = val" />
如果你的项目用的是Vue3,还可以用v-model:options的写法简化事件绑定,Vue2可以用.sync修饰符实现类似效果。
内容的提问来源于stack exchange,提问作者James Lin
相关产品推荐
相关产品推荐

