Skip to content

Vue3 + ElementPlus 实现隐藏表单项数据清除

重写 el-form-itemx-form-item

x-form-item.vue

vue
<template>
  <el-form-item v-bind="$attrs">
    <template v-for="(item, key, i) in $slots" :key="i" v-slot:[key]="slotProps">
        <slot :name="key" v-bind="slotProps"></slot>
      </template>
    </el-form-item>
  </template>
<script setup>
import { onMounted, onUnmounted } from 'vue';

const emit = defineEmits(['onMounted', 'onUnmounted', 'hidden'])

onMounted(() => {
  // console.log('onMounted');
  emit('onMounted')
  emit('hidden', false)
})

onUnmounted(() => {
  // console.log('onUnmounted');
  emit('onUnmounted')
  emit('hidden', true)
})
</script>

调用

form.vue

vue
<template>
  <el-form :model="form">
    <el-form-item label="姓名">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="显示/隐藏年龄">
      <el-switch v-model="form.showAge" />
    </el-form-item>
    <!-- 调用重写的组件 x-form-item -->
    <x-form-item label="年龄" v-if="form.showAge" @onUnmounted="onUnmountedRemoveFields(['age'])">
      <el-input-number v-model="form.age" placeholder="" />
    </x-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">确认</el-button>
      <el-button>取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import XFormItem from './x-form-item.vue'

const form: any = ref({})

const onSubmit = () => {
  console.log(form.value, 'form')
  console.log('submit!')
}

/**
 * 监听到 onUnmounted 事件触发,就清空或者删除表单项对应字段
 * fields 为数组,兼容 一个 el-form-item 里面有多个 el-input 的情况
 * 注意:使用该方法要小心,当整个 form.vue 组件卸载时也会触发,所以需要自行掌握好调用的时机
 */
function onUnmountedRemoveFields(fields: Array<string>) {
  console.log(fields, 'fields')
  fields.map((field: string) => {
    // 置空
    // form.value[field] = null;
    // 删除字段
    delete form.value[field]
  })
}
</script>

补充

其实不一定要重写 el-form-item 组件,只要随便实现 一个组件,利用它的 onUnmounted 钩子,即可实现一样的效果。

a.vue

vue
<template>
  <div v-bind="$attrs">
    <slot></slot>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';

const emit = defineEmits(['onMounted', 'onUnmounted', 'hidden'])

onMounted(() => {
  // console.log('onMounted');
  emit('onMounted')
  emit('hidden', false)
})

onUnmounted(() => {
  // console.log('onUnmounted');
  emit('onUnmounted')
  emit('hidden', true)
})
</script>

form.vue

vue
<template>
  <el-form :model="form">
    <el-form-item label="姓名">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="显示/隐藏年龄">
      <el-switch v-model="form.showAge" />
    </el-form-item>
    <!-- <x-form-item label="年龄" v-if="form.showAge" @onUnmounted="onUnmountedRemoveFields(['age'])">
      <el-input-number v-model="form.age" placeholder="" />
    </x-form-item> -->
    <aVue label="年龄" v-if="form.showAge" @onUnmounted="onUnmountedRemoveFields(['age'])">
      <el-form-item label="显示/隐藏年龄">
        <el-input-number v-model="form.age" placeholder="" />
      </el-form-item>
    </aVue>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">确认</el-button>
      <el-button>取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import aVue from './a.vue'
// import XFormItem from './x-form-item.vue'

const form: any = ref({})

const onSubmit = () => {
  console.log(form.value, 'form')
  console.log('submit!')
}

/**
 * 监听到 onUnmounted 事件触发,就清空或者删除表单项对应字段
 * fields 为数组,兼容 一个 el-form-item 里面有多个 el-input 的情况
 * 注意:使用该方法要小心,当整个 form.vue 组件卸载时也会触发,所以需要自行掌握好调用的时机
 */
function onUnmountedRemoveFields(fields: Array<string>) {
  console.log(fields, 'fields')
  fields.map((field: string) => {
    // 置空
    // form.value[field] = null;
    // 删除字段
    delete form.value[field]
  })
}
</script>