大家好,我是格子,今天我们用如下一个简单的表单填写,来演示另一种方式实现组件之间的通信。
先看效果:父组件对比
通常这种组件我们会为组件定义弹窗的状态(visible)、标题(title)、提交成功的回调方法(success)、表单回显数据(row)等。
用上面的思路代码如下:
子组件
<script setup lang="ts">
import {ref, watch} from "vue";
interface Person {
name: string
age: number
gender: string
}
interface ModalParams {
title: string
row?: Person
visible: boolean
success: () => void
}
const props = defineProps<ModalParams>()
const modal = ref<Person>({} as Person)
const emit = defineEmits<(e: "update:visible", value: boolean) => void>()
// 弹窗状态相关
const visible = ref(false)
watch(() => props.visible, (value) => {
// 处理表单回显逻辑
modal.value = props.row ? props.row : {} as Person
visible.value = value
})
/**
* 模拟保存用户信息接口
*/
const saveInfo = (params: Person) => {
return new Promise((resolve) => {
console.log(params)
setTimeout(() => {
resolve(true)
// 模拟需要保存 1.5 秒
}, 1500)
})
}
/**
* 表单提交相关
*/
const isSubmit = ref(false)
const submitForm = async () => {
isSubmit.value = true
await saveInfo(modal.value)
if (typeof props.success === 'function') {
props.success()
}
isSubmit.value = false
close()
}
/**
* 关闭弹窗
*/
const close = () => {
emit('update:visible', false)
}
</script>
<template>
<el-dialog
width="500px"
:title="props.title"
@close="close"
v-model="props.visible">
<el-form :model="modal">
<el-form-item prop="name" label="姓名">
<el-input v-model="modal.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item prop="age" label="年龄">
<el-input-number
style="width: 100%"
v-model="modal.age"
placeholder="请输入年龄"
step-strictly
:step="1"
:precision="0"
:min="0"
:max="200"
controls-position="right"
></el-input-number>
</el-form-item>
<el-form-item prop="gender" label="性别">
<el-radio-group v-model="modal.gender">
<el-radio value="1">男</el-radio>
<el-radio value="2">女</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" style="text-align: right;">
<el-button @click="close">取 消</el-button>
<el-button type="primary" :loading="isSubmit" @click="submitForm">确 定</el-button>
</div>
</el-dialog>
</template>
父组件
<script setup lang="ts">
import FormModal from "@/components/src/FormModal.vue";
import {ref} from "vue";
import {ElMessage} from 'element-plus'
const visible = ref(false)
const modalTitle = ref('新增')
const handleFillOutForm = () => {
visible.value = true
}
const submitSuccess = () => {
ElMessage.success('操作成功')
}
</script>
<template>
<el-button @click="handleFillOutForm">填写表单</el-button>
<FormModal
v-model:visible="visible"
:title="modalTitle"
:success="submitSuccess"
/>
</template>
改写后的代码:
子组件
<script setup lang="ts">
import {ref} from "vue";
// 弹窗状态
const visible = ref(false)
// 弹窗标题
const modalTitle = ref('')
// 表单数据
const modal = ref<Person>({} as Person)
interface Person {
name: string
age: number
gender: string
}
interface InitModalParams {
title: string
row?: Person
success: () => void
}
/**
* 初始化表单相关
*/
let callbackFunction: () => void
const initModal = ({row, title, success}: InitModalParams) => {
// 处理表单回显逻辑
modal.value = row ? row : {} as Person
visible.value = true
modalTitle.value = title
if (typeof success === "function") {
callbackFunction = success
}
}
/**
* 模拟保存用户信息接口
*/
const saveInfo = (params: Person) => {
return new Promise((resolve) => {
console.log(params)
setTimeout(() => {
resolve(true)
// 模拟需要保存 1.5 秒
}, 1500)
})
}
/**
* 提交表单相关
*/
const isSubmit = ref(false)
const submitForm = async () => {
isSubmit.value = true
await saveInfo(modal.value)
callbackFunction()
isSubmit.value = false
visible.value = false
}
defineExpose({
initModal
})
</script>
<template>
<el-dialog
width="500px"
:title="modalTitle"
v-model="visible">
<el-form :model="modal">
<el-form-item prop="name" label="姓名">
<el-input v-model="modal.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item prop="age" label="年龄">
<el-input-number
style="width: 100%"
v-model="modal.age"
placeholder="请输入年龄"
step-strictly
:step="1"
:precision="0"
:min="0"
:max="200"
controls-position="right"
></el-input-number>
</el-form-item>
<el-form-item prop="gender" label="性别">
<el-radio-group v-model="modal.gender">
<el-radio value="1">男</el-radio>
<el-radio value="2">女</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" style="text-align: right;">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" :loading="isSubmit" @click="submitForm">确 定</el-button>
</div>
</el-dialog>
</template>
父组件
<script setup lang="ts">
import FormModal from "@/components/FormModal.vue";
import {ref} from "vue";
import {ElMessage} from 'element-plus'
const formModalRef = ref()
const handleFillOutForm = () => {
formModalRef.value.initModal({
title: "新增",
success: () => {
ElMessage.success('操作成功')
}
});
}
</script>
<template>
<el-button @click="handleFillOutForm">填写表单</el-button>
<FormModal ref="formModalRef"/>
</template>
可以明显的看到父组件定义的变量减少了,不用单独定义方法处理表单填写成功的回调。