vue 封装Form 表单组件

基于element-plus封装一个表单组件

在components目录下新建一个Form.vue

javascript 复制代码
<template>
    <section class="form-wrap">
        <el-form 
	        :model="formDatas" 
	        label-width="100" 
	        label-position="right" ref="form" 
	        :rules="rules">
            <el-row :gutter="8">
                <template v-for="item in propList" :key="item.id">
                    <el-col :span="8">
                        <el-form-item 
	                        v-if="item.show" 
	                        :key="item.id" 
	                        :prop="item.prop" 
	                        :label="item.label">
                            // input
                            <el-input 
	                             v-else="item.type == 'input'"
	                             v-model="formDatas[item.prop]"
	                            :placeholder="item.placeholder" 
	                            :disabled="item.disabled" 
	                            :style="{ width: item.width }"
	                            clearable>
	                         </el-input>
                            // select
                            <el-select 
                            	v-if="item.type == 'select'"
                                v-model="formDatas[item.prop]"
                                :placeholder="item.placeholder" 
                                :style="{ width: item.width }" 
                                clearable>
                                <el-option 
	                                v-for="option in item.options" 
	                                :label="option.label" 
	                                :value="option.value"
                                    :key="option.value">
                                </el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                </template>
            </el-row>
            // 插槽
            <slot></slot>
        </el-form>
    </section>
</template>

<script setup>
import { ref, reactive, toRefs, inject, onMounted } from 'vue'
import { ElMessage } from 'element-plus'

const form = ref(null)

const emits = defineEmits(['close'])

const data = reactive({
    formDatas: {}
})

// 因为是在Dialog组件中的 form 所以通过依赖注入的方式通信
// 解构注入的属性
const { title, formData, addData } = inject('formObj')

onMounted(() => {
    const dataForm = formData
    formDatas.value = dataForm
})

// 定义表单属性校验
const rules = reactive({
    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
    username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
    phone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }]
})

const { formDatas } = toRefs(data)
// 表单验证
const formValidate = async () => {
    await form.value.validate((valid, fields) => {
        if (valid) {
            const editFormData = formDatas.value
            addData(editFormData)
            if (title === '编辑') {
                ElMessage({
                    message: '修改成功',
                    type: 'success',
                })
            } else {
                ElMessage({
                    message: '新增成功',
                    type: 'success',
                })
            }
            emits('close')
        }
    })
}

function resetForm() {
    form.value.resetFields()
}

defineProps({
    propList: Array,
    formDatas: Object
})

defineExpose({
    formValidate,
    resetForm
})
</script>

<style lang="scss" scoped>
.form-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    padding: 5px;
}
</style>
相关推荐
传人once6 小时前
页面中心圆圈放大效果如何写
开发语言·javascript·ecmascript
用户033307413956 小时前
TypeScript using 与 AsyncDisposableStack:在真实服务端代码中协调多资源清理
前端
web3d5206 小时前
Vue3 地图白屏排查清单:容器、弹窗与 ol-viewport 重复创建
vue.js·gis
daisychey6 小时前
用 Playwright 做多平台内容分发,我踩过的 8 个坑
前端
IT_陈寒8 小时前
为什么你应该学习JavaScript?
前端·人工智能·后端
大龄秃头程序员8 小时前
iOS冷启动监控Demo
前端
光影少年8 小时前
为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?
前端·javascript·算法
掘金酱8 小时前
[稀土掘金 × 火山引擎] AI用量周榜冲刺赛|获奖名单公示
前端·人工智能·后端
泡泡oO9 小时前
“如果你还在用Superpowers,那我不要和你说话”
前端·后端·全栈
维克兜率天9 小时前
趋势过滤:避免被“假突破“反复打脸
前端