封装一个带表格的dialog,走起

我们平时在做各种后台业务时,总是避免不了各种dialog,dialog中还要加上各种表单,表格,掺杂着各式各样的操作,烦不胜烦。
今天,我们就封装一个嵌套着基础表格的dialog,哪里再有dialog带表单的,我上去就是一个回首掏!话不多说,先上图!!!


QQ截图20201117140408.png

跟着我一起封装了这么多组件,我们已经深谙封装套路。props,传值,操作,over。
看代码

//dialog组件
<template>
    <div>
        <el-dialog
          :title="title"
          :visible.sync="dialogVisible"
          :width="width"
            :center="isCenter"
            :fullscreen="isFull"
          >
            <!-- :before-close="handleClose" 弹窗关闭前的回调-->
            <!-- 这里是表格组件,通过接受父组件数据熏染表格 -->
            <custom-table :tableHeader="tableInfo.tableHeader" v-on="$listeners" :tableData="tableInfo.tableData" :config="tableInfo.config" @getcheck="getcheck">
                <template v-slot:handles="t">
                    <el-button-group>
                        <el-link type="primary" @click="edit(t.col)" icon="el-icon-edit">编辑</el-link>
                        <el-link type="danger" @click="deleteId(t.col)">删除<i class="el-icon-delete el-icon--right"></i> </el-link>
                    </el-button-group>
                </template>
            </custom-table>
          <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 CustomTable from '@/mycomponents/CustomTable/index.vue'
    export default {
        inheritAttrs:false,
        components:{
            CustomTable
        },
        props:{
            //确定按钮loading
            loading:{
                type:Boolean,
                default:false,
            },
            //表格数据对象
            tableInfo:{
                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
            },
        },
        data(){
            return {
                checkData:[],//表格多选暂存变量
            }
        },
        //用到了.sync来实现多个双向绑定。这里改变dialog状态时要利用计算属性避免
        //违反单项数据流的思想
        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')
            },
            //获取表格多选数据
            getcheck(val){
                this.checkData = val;
            },
            //点击确定,关闭弹窗,通知父组件进行业务操作
            clickDialog(){
                // 给按钮添加loading状态,避免重复点击请求
                this.$emit('update:loading', true)
                this.$emit('handleconfirm',this.checkData)
            },
            //表格编辑,通知父组件接受要编辑的数据
            edit(t){
                this.$emit('toedit',t)
            },
            //表格删除,通知父组件接受要删除的数据
            deleteId(t){
                this.$emit('todelete',t)
            }
        }
    }
</script>

dialog组件中引入的customTable,就是我们前面封装过的表格组件,表格组件里面还包含着分页组件,所以我们给他们加上$listeners,把需要的事件参数传递过来即可。
我们看一下表格组件

//表格组件部分代码
<template>
    <div>
        <el-table
            class="customer"
            :data="tableData"
            style="width: 100%"
            ref="customTable"
            @selection-change="tableSelectionChange">
            <!-- 循环表头数据,判断列显示类型 -->
            <template v-for="(col,index) in tableHeader">
                <template v-if="col.show">
                    <!-- 多选框 -->
                    <el-table-column v-if="col.type == 'selection'" :label="col.label" :type="col.type" :width="col.width"></el-table-column>
                    <!-- 索引行 -->
                    <el-table-column v-else-if="col.type == 'index'" :label="col.label" :type="col.type" :width="col.width"></el-table-column>
                    <el-table-column v-else-if="col.type == 'image'" :label="col.label" :width="col.width" :prop="col.prop">
                        <template slot-scope="scope">
                            <div class="content-image"><img :src="scope.row[col.prop]"/></div>
                        </template>
                    </el-table-column>
                    <el-table-column v-else-if="col.type == 'date'" :label="col.label" :width="col.width" :min-prop="col.prop">
                        <template slot-scope="scope">
                            <i class="el-icon-time"></i>
                            <span style="margin-left: 10px">{{ scope.row[col.prop] }}</span>
                        </template>
                    </el-table-column>
                    <el-table-column v-else-if="col.type == 'handle'" :label="col.label" :min-width="col.width" :fixed="col.fixed">
                        <template slot-scope="scope">
                            <slot name="handles" :col="(scope)"></slot>
                        </template>
                    </el-table-column>
                    <el-table-column v-else :label="col.label" :min-width="col.width" :prop="col.prop" :formatter="col.formatter?col.formatter:null">
                    </el-table-column>
                </template>
            </template>
        </el-table>
        <pagination v-show="config.total>0" :total="config.total" v-on="$listeners" :page.sync="config.searchList.page" :entry.sync="config.searchList.pageSize" />
    </div>
</template>

这样我们就可以实现基本的弹窗带表格的使用了。我们看我们的引用页面

<template>
    <div class="pages-container">
        <el-button type="primary" @click="openDoor">打开带表格的弹窗</el-button>
        <table-dialog
            :title="dialogConfig.title"
            :visible.sync="dialogConfig.visible" 
            :width="dialogConfig.width"
            :tableInfo="tableInfo"
            :loading.sync="dialogConfig.loading"
            @handleconfirm="confirm"
            @toedit="toEdit($event)"
            @todelete="toDelete($event)"
            @pagechange="getList"
            >
        </table-dialog>
    </div>
</template>

<script>
    import tableDialog from '@/mycomponents/Dialog/table.vue'
    import {tableHeader,tableData,config} from '@/utils/const.js'
    export default {
        components:{tableDialog},
        data(){
            return {
                dialogConfig:{
                    width:'800px',
                    title:'表格弹窗标题',
                    visible:false,
                    loading:false,
                },//弹窗配置
                tableInfo:{
                    tableHeader:tableHeader,
                    tableData:tableData,
                    config:config,
                },//弹窗内表格的数据传递
            }
        },
        methods:{
            //打开弹窗
            openDoor(){
                this.dialogConfig.visible = true;
            },
            //确定弹窗内的业务操作,接收数据
            confirm(val){
                console.log('确认后,选择的数据',val)
                setTimeout(()=>{
                    this.dialogConfig.loading = false;
                },3000)
            },
            //获取表格的分页请求
            getList(e){
                console.log('确认后,分页数据',e)
            },
            //表格编辑操作,接收数据进行处理
            toEdit(e){
                console.log('表格点击编辑后,当前行数据',e)
            },
            //表格删除操作,接收数据进行处理
            toDelete(e){
                console.log('表格点击删除后,当前行数据',e)
            }
        }
    }
</script>

如果你需要在表格中进行其他的操作,也都可以通过修改表格组件来实现。如果这个小功能对你有所帮助的话,点个赞吧大兄弟,谢谢!!!

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

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