Vue3+Vuetify创建是/否单选按钮组件遇props修改报错求解
解决Vue3+Vuetify单选按钮组件的props修改报错问题
你遇到的Unexpected mutation of "selectedValue" prop报错,核心原因是Vue的单向数据流规则:子组件不能直接修改父组件传递过来的props,而你直接把selectedValue这个props绑定给了v-radio-group的v-model,v-model在用户选择时会尝试修改绑定值,这就违反了规则。
下面是两种正确的实现方式,都遵循Vue的数据流规范:
方法一:用计算属性实现自定义v-model(推荐)
这种方式利用Vue的计算属性get/set方法,把v-model的读写操作转成props读取和事件触发,是Vue3官方推荐的自定义组件v-model的写法。
子组件 YesNoRadioButton.vue
<template> <v-radio-group inline :label="title" v-model="localValue"> <v-radio label="Yes" :value="true"></v-radio> <v-radio label="No" :value="false"></v-radio> </v-radio-group> </template> <script setup> import { defineProps, defineEmits, computed } from 'vue' // 定义接收的props const props = defineProps({ title: String, selectedValue: Boolean }) // 定义要触发的事件,遵循Vue的v-model命名规范:update:xxx const emit = defineEmits(['update:selectedValue']) // 计算属性作为中间层,连接props和组件内部的v-model const localValue = computed({ // 读取时返回props的值 get() { return props.selectedValue }, // 修改时触发事件,通知父组件更新数据 set(newVal) { emit('update:selectedValue', newVal) } }) </script>
父组件 Parent.vue
直接用v-model:selectedValue语法糖绑定,它等价于:selectedValue="userAnswer"加上@update:selectedValue="userAnswer = $event":
<template> <YesNoRadioButton title="Are You Sure?" v-model:selectedValue="userAnswer" /> </template> <script setup> import YesNoRadioButton from './YesNoRadioButton.vue' import { ref } from 'vue' const userAnswer = ref(true); </script>
方法二:维护本地状态+监听props同步
如果需要在子组件中对选中值做额外处理,可以用本地响应式变量,同时监听props变化保持同步,值改变时通知父组件。
子组件 YesNoRadioButton.vue
<template> <v-radio-group inline :label="title" v-model="localValue"> <v-radio label="Yes" :value="true"></v-radio> <v-radio label="No" :value="false"></v-radio> </v-radio-group> </template> <script setup> import { defineProps, defineEmits, ref, watch } from 'vue' const props = defineProps({ title: String, selectedValue: Boolean }) const emit = defineEmits(['update:selectedValue']) // 初始化本地变量为props的值 const localValue = ref(props.selectedValue) // 监听props的变化,同步到本地变量(防止父组件修改值时子组件不同步) watch(() => props.selectedValue, (newVal) => { localValue.value = newVal }) // 监听本地变量变化,触发事件通知父组件 watch(localValue, (newVal) => { emit('update:selectedValue', newVal) }) </script>
父组件写法和方法一完全一致
同样用v-model:selectedValue="userAnswer"绑定即可。
这两种方式都能避免直接修改props的问题,保证数据流单向,同时实现单选按钮的双向绑定效果。
内容的提问来源于stack exchange,提问作者user3953989
相关产品推荐
相关产品推荐

