基于element-ui table组件的二次封装

文章目录

相信 element-ui 大家都有所耳闻,table 也是老朋友了,不过在使用它的时候大家是怎么使用的呢?是直接在官网上cv使用吗?这种方式,我相信写起来会有点小难受,反正我感觉要是一共表格就cv一次,对于我来说是有点难受的,但是如果这个 table 表格可以通过一个 json 这种类似的格式进行配置,会不会方便很多呢

配置数据基础分析

  1. 直接复制官网的案例使用 table 组件,会让我们页面的代码增加不说,还会变得不是那么好维护,每次增加删除或者修改,都需要在结构里面去找,而且这种看起来差不多的配置,肯定是能动态生成的话就动态生成,毕竟都是 "懒人"

  2. 开头提到过,通过 json 配置生成,那应该怎么确定这个 json 配置呢?我们不妨写看看官网的案例示例代码,如图:

  3. 可以看到,其实一个列需要的基础属性是 prop 和 label,prop 实现数据的填充,label 就负责表头的显示,所以我们配置的数据,只收应该具备什么,是不是 prop 和 label 呢?所以我们可以写出一个基础的配置数据,如下:

    js 复制代码
    const tableColConfig = [
    	{ prop: 'date', label: '日期' },
    	{ prop: 'name', label: '姓名' },
    	{ prop: 'address', label: '地址' }
    ]
  4. 这个数据只是最基础的,后续讲解会继续扩展

封装 el-table-column

  1. 有了数据之后,我们应该怎么封装,才能通过数据动态生成呢?像这种渲染结构,我们首先想到的必然就是 v-for,也确实如此,所以我们先创建一个 vue 文件来进行封装,如下:

    html 复制代码
    <template>
    	<el-table
    		:border="border"
    		:data="tableData">
    		<!-- 通过 tableColConfig 进行循环渲染 -->
    		<el-table-column
    			v-for="item in tableColConfig"
    			:key="item.prop"
    			:prop="item.prop"
    			:label="item.label"></el-table-column>
    	</el-table>
    </template>
    
    <script>
    export default {
    	props: {
    		// 实际显示的表格数据
    		tableData: {
    			type: Array,
    			default: () => []
    		},
    		// 配置表格的数据
    		tableColConfig: {
    			type: Array,
    			default: () => []
    		},
    		// 是否显示边框
    		border: {
    			type: Boolean,
    			default: true
    		}
    	}
    }
    </script>
    
    <style scoped></style>
  2. 有没有发现我这里多写了一个 border 属性呢,这个属性是来控制 el-table 组件是否展示边框的,有这个配置项的话,那我们的配置文件也需要响应的增加一下,如下:

    js 复制代码
    // 表格列配置
    const tableColConfig = [
    	{ prop: 'date', label: '日期' },
    	{ prop: 'name', label: '姓名' },
    	{ prop: 'address', label: '地址' }
    ]
    
    export default {
    	tableColConfig,
    	border: true
    }
  3. 看起来是不是感觉非常简单呢?那封装好了这个组件之后,我们还需要实际的来使用一下,如下:

    html 复制代码
    <template>
    	<div class="container">
    		<div class="table-box">
    			<!-- v-bind 可以批量绑定属性 -->
    			<JcTable
    				:tableData="tableData"
    				v-bind="tableConfig"></JcTable>
    		</div>
    	</div>
    </template>
    
    <script>
    import JcTable from '@/components/JcTable/index.vue'
    import tableConfig from '@/config/table.config'
    
    export default {
    	components: { JcTable },
    
    	data() {
    		return {
    			tableData: [
    				{
    					date: '2016-05-02',
    					name: '王小虎',
    					address: '上海市普陀区金沙江路 1518 弄'
    				},
    				{
    					date: '2016-05-04',
    					name: '王小虎',
    					address: '上海市普陀区金沙江路 1517 弄'
    				},
    				{
    					date: '2016-05-01',
    					name: '王小虎',
    					address: '上海市普陀区金沙江路 1519 弄'
    				},
    				{
    					date: '2016-05-03',
    					name: '王小虎',
    					address: '上海市普陀区金沙江路 1516 弄'
    				}
    			],
    			tableConfig
    		}
    	}
    }
    </script>
    
    <style scoped>
    .container {
    	width: 100vw;
    	height: 100vh;
    	display: flex;
    	justify-content: center;
    	align-items: center;
    }
        
    .table-box {
    	width: 50%;
    	height: 400px;
    }
    </style>
  4. 关于这个 v-bind 这里不做赘述了,有兴趣的大家可以自行点击跳转到文档查看

  5. 写了这么多,也到了看一眼效果的时候了,也不能光画饼不给吃是不,如图:

  6. 当我们进行了一次封装之后,后续使用这个表格组件就变得非常的简单了

使用插槽强化

  1. 上面实现了一个基础的使用,但是很明显无法满足我们常规的开发需求,这样封装之后,我如果需要再每行加一个按钮呢?或者我需要单独给某一列添加其他dom呢?这些应该怎么解决,比如在官网中的案例效果,如图:

  2. 这种情况在开发中使用 el-table 是非常常见的,而让一个组件在某个位置可以让我们自由编辑替换,大家想到了什么,是不是插槽呢?就是插槽了,关于插槽这里也不做赘述了,而这么多列,我应该怎么才能让我的内容放入到指定的位置中呢?一一对应不难想到,具名插槽

  3. 现在我们已经知道可以通过具名插槽来解决这个问题了,应该如何在渲染的列的时候,动态的添加在我们封装的组件中呢?这时候最开始的配置已经无法满足我们的需求了,还需要一个属性 slotName,当配置的数据中,存在 slotName 时,就使用具名插槽,插槽的名字就是 slotName属性的值,修改的数据如下:

    js 复制代码
    const tableColConfig = [
    	{ prop: 'date', label: '日期' },
    	{ prop: 'name', label: '姓名', slotName: 'name' },
    	{ prop: 'address', label: '地址' },
    	{ prop: 'operate', label: '地址', slotName: 'operate' }
    ]
  4. 在修改封装的组件前,我们不妨先看看再案例中,是如何修改这部分的,如下:

  5. 可以看到,通过这种方式,就可以从el-tale组件中获取到该列中每个单元格对应的值,并且可以在这个范围内自定义的书写dom,所以结合插槽,我们就可以写出如下的代码:

    html 复制代码
    <template>
    	<el-table
    		:border="border"
    		:data="tableData">
    		<el-table-column
    			v-for="item in tableColConfig"
    			:key="item.prop"
    			:prop="item.prop"
    			:label="item.label">
    			<!-- 如果存在 slotName 属性,则加入动态插槽 -->
    			<template #default="scope">
    				<template v-if="item.slotName">
    					<slot
    						:name="item.slotName"
    						:row="scope.row"></slot>
    				</template>
    				<template v-else>
    					<span>{{ scope.row[item.prop] }}</span>
    				</template>
    			</template>
    		</el-table-column>
    	</el-table>
    </template>
    
    <script>
    export default {
    	props: {
    		// 实际显示的表格数据
    		tableData: {
    			type: Array,
    			default: () => []
    		},
    		// 配置表格的数据
    		tableColConfig: {
    			type: Array,
    			default: () => []
    		},
    		// 是否显示边框
    		border: {
    			type: Boolean,
    			default: true
    		}
    	}
    }
    </script>
    
    <style lang="less" scoped></style>
  6. 只是增加了一个if判断,还是比较好理解的,那么增加这个之后,我们只需要按照正常使用插槽的方式使用即可,如下:

    html 复制代码
    <template>
    	<div class="container">
    		<div class="table-box">
    			<JcTable
    				:tableData="tableData"
    				v-bind="tableConfig">
    				<!-- 使用插槽 -->
    				<template #name="{ row }">
    					<span style="color: #f40">{{ row }}</span>
    				</template>
    
    				<template #operate>
    					<el-button type="primary">操作</el-button>
    				</template>
    			</JcTable>
    		</div>
    	</div>
    </template>
  7. 我们来看看现在显示效果,如图:

  8. 在页面的显示中,我们已经可以拿到当前行的数据,具体怎么使用,那就是根据业务自己进行实现了

结语

  1. 使用插槽之后,就已经可以满足日常的基本使用了,如果你还需要其他的需求,可以在此基础上进行扩展
  2. 比如序列号,勾选状态等等,亦或者和其他组件配合,再次封装为一个组件,通过这种分层的思想,可以解决很多业务的问题
相关推荐
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
理想不理想v1 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry2 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x3 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢3 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落3 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt