做个可复用弹窗表单吧

昨天弄了个可复用的表单,今天就把它放进弹窗里面吧,好多小伙伴儿想必都做过类似的事情,总是需要列表编辑或者添加数据,然后弹出一个表单,进行编辑,然后提交后台,今天我们就来封装一下,下次再做,就配置一下数据就轻松生成一个表单弹窗,多好。先上个图给你们:


QQ截图20201119145507.png

怎么样,看上去是不是还不错呢。
表单封装我就不说了,上一篇有讲过。今天就给表单加一个提交后清空重置表单的方法就好了。
在我们的表单组件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)
}

好了,到这里,我们的表单弹窗就封装好了。再来类似的页面,轻轻松松就写完,剩下的时间我们就可以悄悄的摸鱼了。
如果觉得对你有所帮助的话,点个赞吧,谢谢!!

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):