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

895 阅读1分钟

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

image.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>

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