基于element-ui中table表格组件进行二次封装
在平时开发的时候很多情况都会使用到表格和分页功能,所以根据用到的表格功能做一个基础的封装并记录下来,如果有其他功能需要添加直接在此基础上进行扩展即可。
基础功能
1、 表格内容的正常显示
2、 表格内容需要处理后显示(如时间戳转换,枚举值转换等)
3、 表格添加标签、按钮或者操作列内容显示
4、 全选功能
5、 其他原有的属性,如宽度,内容对齐等等属性可以值接使用
6、待扩展
封装组件
1、 基于element-ui的table组件和Pagination组件进行二次封装的组件eleTable
2、 抽离出请求和查询条件的mixins混合
3、 在组件中使用和传入数据
下面分别看下每个组件的完整代码:
1、 基于element-ui的table组件和Pagination组件进行二次封装的组件eleTable
eleTable组件的封装引入了element组件库中的组件,并使用了v-bind 和 v-on来进行对组件间的传参,可以把使用时不用处理的参数直接传递到引入的组件内部,保留组件的属性和功能。另外对于需要特殊处理的内容(如:显示按钮,不同的内容等)使用函数式组件进行渲染。eleTable.vue组件代码如下:
<template>
<div style="width: 1000px;margin: 0 auto;">
<!-- 使用 v-bind和v-on来传递属性和方法-->
<el-table
v-bind="$attrs"
v-on="$listeners">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column
v-for="(item, index) in columns"
:key="index"
v-bind="item">
<template v-if="item.render" v-slot="scope">
<!-- 使用函数式组件进行dom渲染 -->
<render-dom :render="() => item.render(scope.row)"></render-dom>
</template>
</el-table-column>
</el-table>
<el-pagination
v-if="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.pageNum"
:page-sizes="pagination.pageSizes"
:page-size="pagination.pageSize"
v-bind="$attrs"
layout="total, sizes, prev, pager, next"
:total="pagination.total">
</el-pagination>
</div>
</template>
<script>
export default {
name: 'ele-table',
components: {
// 函数式组件注册
renderDom: {
functional: true,
props: {
render: Function
},
render(createElement, renDom) {
return <div>{renDom.props.render()}</div>
}
}
},
props: {
columns: {
type: Array,
default: () => []
},
pagination: Object
},
data() {
return {
}
},
methods: {
// pageSize 改变时会触发
handleSizeChange(args) {
this.$emit('size-change', args)
},
// currentPage 改变时会触发
handleCurrentChange(val) {
this.$emit('page-change', val)
},
},
}
</script>
2、 抽离出请求和查询条件的mixins混合
我们的表格一般还会有各种筛选条件,所以吧这些统一的查询和重置方法提出来成为一个mixins混合,在使用的组件里面引入(如果后端接口返回的数据比较统一,也可以将查询翻页等功能直接封装在表格组件中,根据业务需要封装)。下面是mixins.js代码:
export default {
data() {
return {
// 分页
pagination: {
pageNum: 1,
pageSize: 10,
total: 4,
pageSizes: [10, 20, 30, 40, 50],
},
// 表格数据
dataList: [],
// 返回参数字段名
dataKey: 'dataKey',
}
},
methods: {
handleQuery() {
const { pageNum, pageSize } = this.pagination
// tableListUrl 封装的接口名
this.$api(this.tableListUrl, {
...this.formData,
pageParam: {
pageNum,
pageSize,
},
}).then(res => {
if (!res) return
this.pagination.total = res.pageParam ? res.pageParam.total : 0
this.dataList = res[this.dataKey]
})
},
// 查询列表
queryHandle() {
const data = this.formData
// 时间处理
if (data.timeRange && data.timeRange.length !== 0) {
data.startTime = data.timeRange[0]
data.endTime = data.timeRange[1]
} else {
data.startTime = null
data.endTime = null
}
this.pagination.pageNum = 1
this.handleQuery()
},
// 重置列表
resetHandle() {
const data = this.formData
Object.keys(data).forEach(key => {
data[key] = null
})
this.pagination.pageNum = 1
this.handleQuery()
},
// 改变页码
handlePageChange(page) {
this.pagination.pageNum = page
this.handleQuery()
},
// 改变页数
handleSizeChange(size) {
this.pagination.pageSize = size
this.pagination.pageNum = 1
this.handleQuery()
},
},
}
3、 在组件中使用和传入数据
在使用封装好的组件时,直接引入eleTable组件和mixins文件,并传入相应的数据和属性即可。详细代码如下:
<template>
<div>
<ele-table
:data="dataList"
:columns="columnsList"
:pagination="pagination"
@page-change="handlePageChange"
@size-change="handleSizeChange"
@selection-change="handlechange">
</ele-table>
</div>
</template>
<script>
import eleTable from './table/eleTable'
import tabelMixin from './table/tableFinMixins'
export default {
mixins: [tabelMixin],
components: {
eleTable
},
data() {
return {
// 查询条件数据
formData: {
starTime: '',
endTime: ''
},
// 封装的接口地址
tableListUrl: '',
// 表单数据
dataList: [{
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 弄'
}],
// 表单列数据
columnsList: [
{
prop: 'date',
label: '日期',
width: '120'
},
{
prop: 'name',
label: '姓名',
width: '180',
render: m => {
return (
<span>
<span style="color: red;">{m.name}</span>
<span style="color: blue; margin-left: 10px;">{m.name}</span>
</span>
)
}
},
{
prop: 'address',
label: '地址',
width: '220'
},
{
prop: 'handle',
label: '操作',
render: () => {
return (
<div>
<span onClick={this.handleDeatils} style="color:blue;">详情</span>
<span onClick={this.handleDelete} style="color:red;margin-left: 10px;">删除</span>
</div>
)
}
}
]
}
},
methods: {
handleDeatils() {
console.log('详情')
},
handleDelete() {
console.log('删除')
},
handlechange(val) {
console.log(val)
}
}
}
</script>
使用效果
时间可以进行转换成想展示的格式,内容可以添加事件进行触发,支持多选等等功能。