Vue3条件包裹父组件不影响子组件及modelValue只读警告问题
解决方案
一、修复「modelValue 只读」警告
Vue3 中 props 是只读的,直接用 v-model 绑定 props.modelValue 会触发修改只读属性的警告。推荐通过双向计算属性处理:
<template> <!-- 条件渲染 el-col 包裹 --> <el-col v-if="wrapWithCol" :xs="column.xs" :sm="column.sm" :lg="column.lg" :xl="column.xl"> <el-form-item :prop="formItems.prop" :label="formItems.label" :rules="formItems.rules" > <el-input v-model="localValue" :placeholder="props.placeholder" :type="props.type" :autocomplete="props.autocomplete" :suffix-icon="props.icon" /> </el-form-item> </el-col> <!-- 不包裹时直接渲染内容 --> <template v-else> <el-form-item :prop="formItems.prop" :label="formItems.label" :rules="formItems.rules" > <el-input v-model="localValue" :placeholder="props.placeholder" :type="props.type" :autocomplete="props.autocomplete" :suffix-icon="props.icon" /> </el-form-item> </template> </template> <script setup> import { computed } from 'vue'; const emit = defineEmits(["update:modelValue"]); const props = defineProps({ modelValue: { type: [String, Number], required: true, default: "", }, // 新增控制是否用 el-col 包裹的属性 wrapWithCol: { type: Boolean, default: true, }, type: { type: String, required: false, default: "", }, placeholder: { type: String, required: false, default: "", }, autocomplete: { type: String, required: false, default: "off", }, icon: { type: String, required: false, default: "", }, formItems: { type: Object, required: false, }, column: { type: Object, required: false, default: { xs: 24, sm: 24, lg: 8, xl: 8 }, }, }); // 双向计算属性,同步 props 和 emit 事件 const localValue = computed({ get() { return props.modelValue; }, set(newVal) { emit('update:modelValue', newVal); } }); </script>
二、实现条件性 el-col 包裹
通过新增的 wrapWithCol props 控制渲染逻辑:
- 当
wrapWithCol为true时,用 el-col 包裹表单项 - 为
false时,直接渲染内部的表单组件,不添加 el-col 布局
父组件调用示例
<template> <!-- 默认开启 el-col 包裹 --> <InputColumn :column="{ xs: 24, sm: 12, lg: 8, xl: 6 }" :formItems="{ label: 'Prefix', prop: 'prefix', rules: [ { required: true, message: 'Enter value', trigger: 'change', }, ], }" v-model="prefix" placeholder="Prefix" /> <!-- 关闭 el-col 包裹 --> <InputColumn :wrapWithCol="false" :formItems="{ label: 'No Col Prefix', prop: 'noColPrefix', rules: [ { required: true, message: 'Enter value', trigger: 'change', }, ], }" v-model="noColPrefix" placeholder="No Col Prefix" /> </template> <script setup> import { ref } from 'vue'; const prefix = ref(''); const noColPrefix = ref(''); </script>
额外优化
父组件中的 @update="(v) => (prefix = v)" 是冗余代码,v-model 已经自动处理了 update:modelValue 事件,直接删除即可。
内容的提问来源于stack exchange,提问作者Kishan Bhensadadiya
相关产品推荐
相关产品推荐

