You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 08:45:38