单选框组件接收传值更新失败————强制组件刷新
摘要:
单选框组件CustomImageRadio在接收v-model传值时可能出现更新失败问题。原因在于组件可能未正确监听绑定值的变化。解决方法是通过添加:key="componentKey"绑定,并在数据更新时强制更改key值触发组件重新渲染。文中展示了表单中的使用示例,以及完整的单选框组件封装代码,包含动态图片切换和样式处理。关键点包括:1) 使用watch监听选中值变化;2) 通过key值强制刷新;3) 原生单选框隐藏并用图片替代的样式实现。
问题所在
组件监听机制可能缺失。性别单选框CustomImageRadio 组件也许没有监听 v-model 绑定值的变化,进而无法更新自身的选中状态。
封装的组件样式
解决方式
:key=“componentKey”
<el-form-item label="性 别" prop="gender" class="theme-line">
<CustomImageRadio
name="gender"
v-model="selectedGender"
:key="componentKey" <!-- 添加 key 绑定 -->
:options="[
{
label: '男',
value: 0,
uncheckedImg: require('@/assets/image/patient/no.png'), // 替换实际图片路径
checkedImg: require('@/assets/image/patient/yes.png')
},
{
label: '女',
value: 1,
uncheckedImg: require('@/assets/image/patient/no.png'), // 替换实际图片路径
checkedImg: require('@/assets/image/patient/yes.png')
}
]"
/>
</el-form-item>
// 通过更改 key 强制组件重新渲染
componentKey.value += 1;
const componentKey = ref(0);
// 查看
const LookInfo = (item) => {
form.value = { ...item };
selectedGender.value = item.gender;
// 通过更改 key 强制组件重新渲染
componentKey.value += 1;
};
单选框样式封装代码
<template>
<div class="custom-image-radio-group">
<label
v-for="(option, index) in options"
:key="index"
class="custom-image-radio-label"
>
<input
type="radio"
:name="name"
:value="option.value"
v-model="selectedValue"
class="custom-image-radio-input"
>
<!-- 未选中状态的图片 -->
<img
:src="option.uncheckedImg"
alt="unchecked"
class="custom-image-radio-img"
>
<span class="custom-image-radio-text">{{ option.label }}</span>
</label>
</div>
</template>
<script setup>
import {ref, defineProps, watch} from 'vue';
const props = defineProps({
name: {
type: String,
required: true
},
options: {
type: Array,
required: true,
default: () => [
{
label: '男',
value: '0',
uncheckedImg: require('@/assets/image/patient/no.png'), // 替换实际图片路径
checkedImg: require('@/assets/image/patient/yes.png')
},
{
label: '女',
value: '1',
uncheckedImg: require('@/assets/image/patient/no.png'),
checkedImg: require('@/assets/image/patient/yes.png')
}
]
},
modelValue: {
type: String,
default: ''
}
});
// eslint-disable-next-line no-undef
const emits = defineEmits(['update:modelValue']);
const selectedValue = ref(props.modelValue);
watch(selectedValue, (newVal) => {
emits('update:modelValue', newVal);
});
</script>
<style scoped>
.custom-image-radio-group {
display: flex;
align-items: center;
}
.custom-image-radio-label {
display: flex;
align-items: center;
margin-right: 20px;
cursor: pointer;
}
.custom-image-radio-input {
display: none; /* 隐藏原生单选框 */
}
.custom-image-radio-img {
width: 20px; /* 根据实际图片调整大小 */
height: 20px;
margin-right: 5px;
transition: opacity 0.3s ease;
}
/* 选中状态切换图片 */
.custom-image-radio-input:checked + .custom-image-radio-img {
content: url('@/assets/image/patient/yes.png'); /* 男的选中图,实际要根据选项动态处理,这里只是示例思路,下面会优化 */
/* 实际更灵活的做法是结合动态绑定,这里先简单演示,完整优化见下方说明 */
}
.custom-image-radio-text {
font-size: 14px;
}
</style>