昨天弄了个可复用的表单,今天就把它放进弹窗里面吧,好多小伙伴儿想必都做过类似的事情,总是需要列表编辑或者添加数据,然后弹出一个表单,进行编辑,然后提交后台,今天我们就来封装一下,下次再做,就配置一下数据就轻松生成一个表单弹窗,多好。先上个图给你们:
怎么样,看上去是不是还不错呢。
表单封装我就不说了,上一篇有讲过。今天就给表单加一个提交后清空重置表单的方法就好了。
在我们的表单组件methods里面先写一个
//重置表单初始数据并移除校验效果
resetForm(){
this.$refs['customForm'].resetFields();
},
然后我们先再来封装弹窗表单组件。和表格弹窗差不多,我们先把弹窗的属性props定义好,然后给弹窗里面添加一个表单需要用到的数据对象dialogForm。这里我们注意,要把封装好的表单里面isHandle的操作栏属性为false,因为弹窗带了操作栏,我们利用这个操作栏来进行业务回调。
其他的弹窗属性和方法与表格弹窗基本一致。
<template>
<div>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
:width="width"
:center="isCenter"
:fullscreen="isFull"
:destroy-on-close="true"
>
<!-- :before-close="handleClose" 弹窗关闭前的回调-->
<!-- 这里是表单组件,通过接受父组件数据熏染单 -->
<custom-form :myForm="dialogForm.myForm" :isHandle="false" :formData="dialogForm.formData" ref="dynamic" :inline="false" v-on="$listeners">
</custom-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button :loading="vLoading" type="primary" @click="clickDialog">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import CustomForm from '@/mycomponents/CustomForm/index.vue'
export default {
inheritAttrs:false,
components:{
CustomForm
},
props:{
//确定按钮loading
loading:{
type:Boolean,
default:false,
},
//表单需要用到的数据
dialogForm:{
type:Object,
default:()=>{}
},
//窗口可见状态
visible:{
type:Boolean,
default:false,
},
//弹窗标题
title:{
type:String,
default:'标题'
},
//弹窗宽度
width:{
type:String,
default:'50%'
},
//弹窗是否居中
isCenter:{
type:Boolean,
default:false
},
//弹窗是否全局显示
isFull:{
type:Boolean,
default:false
},
},
computed:{
dialogVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
},
//确定按钮loading事件
vLoading: {
get() {
return this.loading
},
set(val) {
this.$emit('update:load', val)
}
}
},
methods:{
//关闭前的回调
handleClose(){
this.$emit('beforeclose','close')
},
//点击确定,关闭弹窗,通知父组件进行业务操作
async clickDialog(){
//先校验,然后校验通过通知父组件当前填写的数据信息,让父组件进行业务操作
let flag = await this.$refs.dynamic.submitForm();
if(flag){
this.$emit('update:loading', true)
let val = {...this.dialogForm.myForm}
this.$emit('handleconfirm',val);
}
},
}
}
</script>
然后我们看页面使用:
<template>
<div class="pages-container">
<el-button type="primary" @click="openDoor">打开带表单的弹窗</el-button>
<form-dialog
ref="dialogs"
:title="dialogConfig.title"
:visible.sync="dialogConfig.visible"
:width="dialogConfig.width"
:dialogForm="dialogForm"
:loading.sync="dialogConfig.loading"
@handleconfirm="confirm"
>
</form-dialog>
</div>
</template>
页面里我们发现多了一个dialogForm属性,这个是我们在使用的时候传递的表单数据。然后定义了一个ref,是为了找到我们表单的refs重置方法,来进行表单提交成功后的表单重置。
这里说到一个坑,我们再进行一次业务操作后,关闭弹窗,再次打开后,会遗留上次的填写数据,如果直接执行表单的this.$refs[formName].resetFields()方法,不能完全清空表单(自定义组件,比如自己封装的图片,select组件等)数据,而且会存在校验结果显示在下面。很讨厌。
这里我们要先手动清空表单的各个属性值,然后再调用resetFields(),这个方法是用来对该表单项进行重置,将其值重置为初始值并移除校验结果的,而不是用来清空的,这里要注意。
<script>
import FormDialog from '@/mycomponents/Dialog/form.vue'
//我们在dialogForm中定义好表单需要的配置数据
import {dialogForm} from './const.js'
//引入了一个清空表单的方法,对表单进行遍历,
//然后区分对象属性值中是普通string类型还是数组类型,清空成字符串和空数组
import {clearObject} from '@/utils/index.js'
export default {
components:{FormDialog},
data(){
return {
dialogForm:dialogForm,
dialogConfig:{
width:'800px',
title:'表格弹窗标题',
visible:false,
loading:false,
},//弹窗配置
}
},
methods:{
//打开表单弹窗
openDoor(){
this.dialogConfig.visible = true;
},
//弹窗点击确认按钮,获取数据成功提交给后台,关闭loading和弹窗,清空表单
confirm(val){
setTimeout(()=>{
//关闭loading
this.dialogConfig.loading = false;
//关闭弹窗 在这之前取得val后发送给后台进行业务回调
this.dialogConfig.visible = false;
//找到我们表单组件的ref属性,然后作为参数提交给清空方法,执行重置表单API
let ref = this.$refs.dialogs.$refs.dynamic;
//封装的清空表单方法(//循环对象属性,重置各个属性值为空;)
clearObject(this.dialogForm.myForm,this,ref).then();
console.log(val);
},3000)
},
}
}
</script>
我们看到上面提到一个清空对象属性值的方法,这里我写一下这段代码
//obj是我们要清空的表单object;
//_this就是我们页面的this,用它来做指向
//ref是我们要找的表单组件的ref,利用它来执行表单组件里面的重置方法
//$nextTick是等页面表单清空并渲染后再执行重置方法;
export function clearObject(obj,_this,ref){
let data = {...obj}
for (var key in data){
if(data[key].isArray){
data[key] = []
}else{
data[key] = ''
}
};
_this.myForm = data;
_this.$nextTick(()=>{
ref.resetForm();
})
return Promise.resolve(data)
}
好了,到这里,我们的表单弹窗就封装好了。再来类似的页面,轻轻松松就写完,剩下的时间我们就可以悄悄的摸鱼了。
如果觉得对你有所帮助的话,点个赞吧,谢谢!!