vue3 父组件调用子组件 el-drawer 抽屉
之前 Vue3 只停留在理论,现在项目重构,刚好可以系统的实战一下,下面是封装了一个抽屉表单组件,直接在父组件中通过调用子组件的方法打开抽屉:
父组件:
<template>
<div id="app">
<div @click="getChildValue">open</div>
<custom-form
ref="childRef"
:fields="fields"
:form="form"
:rules="rules"
:saveForm="saveForm"
></custom-form>
</div>
</template>
<script setup>
import CustomForm from "@/components/CustomModelForm";
import { reactive } from "vue";
const formData = reactive({
form: {
name: "",
email: "",
date: "",
password: "",
},
fields: [
{
prop: "name",
label: "Name",
component: "el-input",
props: { placeholder: "Enter your name" },
},
{
prop: "email",
label: "Email",
component: "el-input",
props: { placeholder: "Enter your email" },
},
{
prop: "date",
label: "Date",
component: "el-date-picker",
props: {
placeholder: "Enter your date",
format: "YYYY-MM-DD",
valueFormat: "YYYY-MM-DD",
},
},
{
prop: "password",
label: "Password",
component: "el-input",
props: { placeholder: "Enter your password", type: "password" },
},
],
rules: {
name: [
{ required: true, message: "Please input your name", trigger: "blur" },
],
email: [
{ required: true, message: "Please input your email", trigger: "blur" },
],
password: [
{
required: true,
message: "Please input your password",
trigger: "blur",
},
],
},
});
const { form, fields, rules } = toRefs(formData);
const childRef = ref(null);
function getChildValue() {
childRef.value?.open();
}
function saveForm() {
console.log(form.value);
}
</script>
子组件:
<template>
<el-drawer
v-model="drawer"
:title="title"
:size="width"
:before-close="resetForm"
>
<el-form :model="form" :rules="rules" ref="customForm" label-width="auto">
<el-form-item
v-for="field in fields"
:key="field.prop"
:label="field.label"
:prop="field.prop"
>
<component
:is="field.component"
v-bind="field.props"
v-model="form[field.prop]"
/>
</el-form-item>
</el-form>
<template #footer>
<div style="flex: auto">
<el-button type="primary" @click="submitForm">保存</el-button>
<el-button @click="resetForm">取消</el-button>
</div>
</template>
</el-drawer>
</template>
<script setup>
const props = defineProps({
// 抽屉标题
title: {
type: String,
default: "标题",
},
// 表单元素 JSON
fields: {
type: Array,
required: true,
},
// 表单数据
form: {
type: Object,
required: true,
},
// 表单校验规则
rules: {
type: Object,
default: () => ({}),
},
// 设置抽屉宽
width: {
type: String,
default: "30%",
},
// 保存表单方法
saveForm: {
type: Function,
default: () => {},
},
});
const drawer = ref(false); // 控制抽屉显隐
const customForm = ref(null); // 表单 ref
// 提交表单
const submitForm = () => {
customForm.value.validate((valid) => {
if (valid) {
props.saveForm();
resetForm();
} else {
console.log("error submit!!");
return false;
}
});
};
// 打开抽屉
function open() {
drawer.value = true;
}
// 关闭抽屉
const resetForm = () => {
customForm.value.resetFields();
drawer.value = false;
};
defineExpose({
open,
});
</script>
这里主要用来 ref 和 defineExpose,其中 ref
获取了子组件的实例,而 defineExpose
是一个用于在 <script setup>
语法糖中暴露组件内部的属性或方法给父组件的函数。通过使用 defineExpose
,你可以控制哪些属性和方法可以被外部访问,从而增强组件的封装性和安全性。