基于elementplus的弹窗嵌套表单进行二次封装
所见即所得:简单封装方便工作
ProForm.vue代码:
<!--* @Author: 忆往昔* @LastEditTime: 2024-01-6 14:36:00* @email: 15871856064@163.com
-->
<template><div class="penk-form-container"><el-dialogv-model="visible1":fullscreen="props.fullscreen":draggable="props.draggable":title="props.title":width="props.width || '50%'"><el-formref="ruleFormRef"label-width="120px"size="large":model="form":rules="props.formConfig.rules"><template v-for="item in props.formConfig.formItemConfig" :key="item.prop"><el-form-item:label="item.label + ':'":style="{ display: item.hidden == true ? 'none' : '' }":prop="item.prop"><!-- 输入框 --><el-inputv-if="item.type == 'input'"v-model="form[item.prop]":placeholder="item.placeholder || ''":clearable="item.clearable":disabled="item.disabled":type="item.inputType":row="item.row":style="{ width: item.width + 'px' }"/><!-- 下拉框 --><el-selectv-else-if="item.type == 'select'"v-model="form[item.prop]":placeholder="item.placeholder":clearable="item.clearable":disabled="item.disabled":style="{ width: item.width + 'px' }"><el-optionv-for="option in item.data":key="option.value":label="option.label":value="option.value":disabled="option.disabled"/></el-select><!-- 多选框 --><el-checkbox-groupv-else-if="item.type == 'checkbox'"v-model="form[item.prop]":placeholder="item.placeholder":clearable="item.clearable":disabled="item.disabled":style="{ width: item.width + 'px' }"><el-checkboxv-for="option in item.data":key="option.value":label="option.value":disabled="option.disabled">{{ option.label }}</el-checkbox></el-checkbox-group><!-- 单选框 --><el-radio-groupv-else-if="item.type == 'radio'"v-model="form[item.prop]":placeholder="item.placeholder":clearable="item.clearable":disabled="item.disabled":style="{ width: item.width + 'px' }"><el-radio:label="option.value"size="large"v-for="option in item.data":key="option.label">{{ option.label }}</el-radio></el-radio-group></el-form-item></template></el-form><template #footer><span class="dialog-footer"><el-button @click="visible1 = false">取消</el-button><el-button type="primary" @click="confirm(ruleFormRef)"> 确定 </el-button></span></template></el-dialog></div>
</template><script setup>
import { ref, reactive, watch, defineEmits, onMounted } from 'vue'
import { ElMessage } from 'element-plus'let form = reactive({})
const visible1 = ref(true)
const ruleFormRef = ref()const props = defineProps({formData: {type: Object,default: () => {}},formConfig: {type: Object,default: () => {}},visible: {type: Boolean,default: false},width: {type: String,default: '520px'},title: {type: String,default: '新增'},fullscreen: {type: Boolean,default: false},draggable: {type: Boolean,default: false},'append-to-body': {type: Boolean,default: false},'close-on-click-modal': {type: Boolean,default: false}
})// 生成事件对象,数组中就是对象名
const emit = defineEmits(['update:visible', 'confirm'])// 监听父组件的visible,用来简介控制el-dialog的弹框开关,一般是用于开
watch(() => props.visible,(n, o) => {visible1.value = n}
)
// 监听el-dialog显示状态,再通过@update:visible 通知父组件,一般是用于关
watch(visible1, (n, o) => {emit('update:visible', n)
})// 每次触发,就证明父组件点了修改或者添加的按钮,传递了一个新的formData
// 需要重新给form 赋值,并且,对该表单项进行重置
watch(() => props.formData,(n, o) => {resetForm(ruleFormRef.value)form = reactive(n)}
)// 确定按钮触发
const confirm = async (formEl) => {if (!formEl) returnawait formEl.validate((valid, fields) => {if (valid) {emit('confirm', form)} else {console.log('error submit!', fields)ElMessage({showClose: true,message: '请完善表单信息!',type: 'error'})}})
}// 重置表单
const resetForm = (formEl) => {if (!formEl) returnformEl.resetFields()
}onMounted(() => {console.log(props.formConfig);// 初始化 配置弹框是否可显示visible1.value = props.visible// 初始化 配置formDataprops.formConfig.formItemConfig.map((item) => {form[item.prop] = ''})
})
</script><style lang="scss" scoped>
.penk-form-container {.el-table-border {border: 1px #eee solid;}:deep(.el-dialog__body) {border-top: 1px solid #eee;}
}
</style>
组件使用示例:
<template><MyTable:tableData="tableData":columns="columns":total="total":currentPage="listQuery.pageNo":pageSize="listQuery.pageSize"@changeTableData="changeTableData"><!-- <template #check="{ slotProps }"><el-tag class="ml-2" :type="slotProps.check ? 'success' : 'danger'">{{ checkFilter(slotProps.check) }}</el-tag></template> --><template #operator="{ slotProps }"><el-button type="primary" @click="setData('edit', slotProps)">编辑</el-button><el-button type="primary" @click="handleAddItem">新增</el-button><el-button type="primary" @click="handleEditItem(slotProps)">修改</el-button><el-button type="danger" @click="handleDel(slotProps)">删除</el-button></template></MyTable><!-- 表单弹框 --><ProForm:title="title":formConfig="formConfig":formData="formData"v-model:visible="visible"append-to-body@confirm="saveItem"/>
</template><script setup>
import { ref, onMounted } from 'vue'
import MyTable from '@/components/MyTable/MyTable.vue'
import ProForm from '@/components/ProForm/ProForm.vue'let listQuery = ref({pageNo: 1,pageSize: 10
})
const tableData = ref([{ number: '001', numberplate: '京A12345', date: '2022-01-01', check: '正常', operator: '编辑' },{ number: '002', numberplate: '京B67890', date: '2022-02-01', check: '正常', operator: '编辑' },{ number: '003', numberplate: '京C24680', date: '2022-03-01', check: '故障', operator: '编辑' },{ number: '004', numberplate: '京D13579', date: '2022-04-01', check: '正常', operator: '编辑' },{ number: '005', numberplate: '京E97531', date: '2022-05-01', check: '正常', operator: '编辑' }
])
let total = ref(0)/*** prop:数据项列名* label:列名展示名* fixed:固定列 true/right/left* width:列宽* show-overflow-tooltip* type:对应列的类型 selection / index / expand* sortable:true/false* selectable:Function* formatter:格式化内容 function(row, column, cellValue, index)**/
let columns = ref([{ prop: 'number', label: '车牌自编号' },{ prop: 'numberplate', label: '车牌号' },{ prop: 'date', label: '出厂日期' },{ prop: 'check', label: '车辆状态' },{ prop: 'operator', label: '操作', fixed: 'right' }
])onMounted(() => {})const changeTableData = (pageNum, pageSize) => {listQuery.value.pageNo = pageNumlistQuery.value.pageSize = pageSizegetCarList()
}const visible = ref(false) // 控制弹窗开关
const title = ref('') // 弹窗标题
const formData = ref({}) // 表单数据// 表单配置项
const formConfig = {formItemConfig: [{label: '类型名',prop: 'typeName',type: 'input'},{label: '父级类型名',prop: 'parentId',type: 'select',data: []}],rules: {typeName: [{required: true,message: '请输入类型名',trigger: 'blur'}]}
}// 添加数据按钮
const handleAddItem = () => {visible.value = truetitle.value = '新增'formData.value = {}
}// 修改数据按钮
const handleEditItem = (row) => {visible.value = truetitle.value = '修改'formData.value = row
}// 表单提交
const saveItem = (form) => {console.log('提交', form)
}
</script>