vue之JSX封装table

[[toc]]

封装之前先看下

babel-plugin-transform-vue-jsx

基于ElementUI的table二次封装

最近搞中台开发,用的ElementUI的Table组件比较多,几乎每个页面都用,相比react的antd,饿了么的table就相对臃肿了,可能是因为框架的原因吧。

本次封装用的jsx语法,vue模板拓展性不是特别显优势,没有jsx灵活。想看jsx在vue中怎么使用的请转看下之前的文章

组件封装源码

//EnhanceTable.jsx
import table from "../mixins/table"

export default {
mixins: [table],
props: {
otherTableParams: { // 设置table其他参数
type: Object,
default: function () {
return {}; // Object/Array的属性必须使用函数返回默认值 箭头函数不行
}
},
otherPaginationParams: { // 设置分页其他参数
type: Object,
default: function () {
return {};
}
},
tableColumn: { // table的column
type: Array,
default: function () {
return [];
}
},
multiple: {
type: Boolean,
default: false
},
},
methods: {
handleButtons(item, record) {
// 处理操作部分按钮 -> 可以在外面自定义,必须是jsx
if (item.handleButtons) return item.handleButtons(record);
return (
!!item.list.length && item.list.map((item) => {
return (
<el-button
disabled={item.disabled}
key={item.title}
type="text"
size="small"
style={item.styles}
onClick={() => item.cb(record)}
>
{item.title}
</el-button>
)
})
);
}
// handleCurrentChange(val) {
// this.$emit('currentChange', val);
// },
},
mounted() {
},
render() {
const {tableOptions, paginationOptions, paginationOptionsMethod, tableOptionsMethod, otherTableParams, tableColumn, multiple} = this;
return (
<div>
<el-table
{...{
props: {
...tableOptions,
...otherTableParams.props,
},
on: {
...tableOptionsMethod,
...otherTableParams.on
}
}}
>
{/* table多选 */}
{
multiple && (
<el-table-column
type="selection"
width="55"
fixed={'left'}
/>
)
}
{/* table列表 */}
{
tableColumn.map((item) => {
if (item.type === 'button') {
// 操作部分
return (
<el-table-column
label={item.label || '操作'}
width={item.width || '88'}
fixed={item.fixed || 'right'}
{...{
scopedSlots: {
default: ({row}) => {
return this.handleButtons(item, row)
}
}
}}
/>
)
}
return (
<el-table-column
props={item}
key={item.prop}
{...{
// 自定义的渲染方式,拓展性
scopedSlots: {
default: ({row}) => {
return item.render ? item.render(row[item.prop], row) : row[item.prop]
}
}
}}
/>
)
})
}
</el-table>
{/*分页*/}
<el-pagination
{...{
class: paginationOptions.class, // 支持拓展
props: {
...paginationOptions,
},
on: {
...paginationOptionsMethod
},
}}
/>
</div>
);
}
};

EnhanceTable 文档

组件使用

<template>
<enhance-table ref="table" :multiple="true" :otherTableParams="otherTableParams" :tableColumn="column"
/>
</template>
<script>
import EnhanceTable from "../components/EnhanceTable"

export default {
data() {
return {
otherTableParams: {// table的参数
props: {
border: true,
stripe: true,
size: 'small',
'default-sort': {prop: 'createTime', order: 'ascending'}
}
},
otherPaginationParams:{},// 分页的参数
column: [ // table的列
{
prop: "roleId",
label: "序号",
width: 100,
},
{
prop: 'roleName',
label: "角色名称",
'width': "110"
},
{
prop: "createTime",
label: "创建时间",
sortable: true
},
{
prop: 'roleName',
label: "角色名称",
//formatter 完全可以用render代替
render: (text, record) => { // 当前行的值,当前行数据
// console.log(record);
return <h4>{text}</h4>
},
},
{ // 最后的操作列,可根据list里面展示要操作的按钮,和回调
type: 'button',
width: '118',
label: "设置",
list: [
{title: '查看', disabled: false, styles: {color: '#777'}, cb: this.seeHandle},
{title: '编辑', cb: this.editHandle}
],
// handleButtons: () => (<div>111</div>) // 自定义的内容
}
]
}
},
components: {EnhanceTable},
methods: {
queryList() { // 子组件默认的请求名称
this.$nextTick(async () => {
// 因为当前算是父组件,当执行到父组件的created周期才会执行它的子组件,所以这个时候子组件的data的一些方法获取不到,或者可以在mounted周期里面执行异步请求
const {paginationOptions: {pageSize, currentPage}, handlePageData} = this.$refs.table;// 获取子组件mixins里面的参数
const {data: {items, page: {totalRecord}}} =
await this.$fetch(`http://xx..xx/role?pageSize=${pageSize}&pageNum=${currentPage}`, {
headers: {
Authentication: 'xxxxx'
},
});
handlePageData(items, totalRecord); // mixin里面统一处理
});
},
editHandle(...options) {
console.log(options, '编辑');
},
seeHandle(...options) {
console.log(options, '查看');
}
},
created() {
this.queryList();//必须是这个名称
},
mounted() {
}
}
</script>

<style type="text/scss" lang="scss" scoped>

</style>

最后在送一个当前使用的mixins

// table.mixins.js
const table = {
data() {
return {
tableOptions: {
data: [], // 列表数据
border: true, // 带边框
style: "width: 100%",
size: "small",
multipleSelection: [], // 列表多选
},
tableOptionsMethod: {
"selection-change": this.handleSelectionChange
},
paginationOptions: {
class: "fyDiv",
background: true, // 带有背景色
layout: "total, sizes, prev, pager, next",
pageSizes: [10, 20, 30, 40],
total: 0, // 应用列表总数量
pageSize: 10, // 当前分页数量
currentPage: 1, // 当前页数第一页
showPage: false, // 是否显示分页组件,必须total总数也要小于当前要展示的页数
},
paginationOptionsMethod: {
"size-change": this.handleSizeChange,
"current-change": this.handleCurrentChange
}
};
},
methods: {
// 获取数据回调处理分页和data
handlePageData(data, total) {
this.tableOptions.data = data;
// 如果还有下一页,则显示分页插件
if (total > 10) {
this.paginationOptions.showPage = false;
} else {
this.paginationOptions.showPage = true;
this.paginationOptions.currentPage = 1;
this.paginationOptions.pageSize = 10;
}
this.paginationOptions.total = total;
},
// 选项变化
handleSelectionChange(multipleSelection) {
console.log(multipleSelection, "选中");
this.tableOptions.multipleSelection = multipleSelection;
},
// 改变页数
handleCurrentChange(currentPage) {
this.paginationOptions.currentPage = currentPage;
this.queryList ? this.queryList() : this.$parent.queryList();
},
// 选择页数
handleSizeChange(currentSize) {
this.paginationOptions.pageSize = currentSize;
this.paginationOptions.currentPage = 1;
this.queryList ? this.queryList() : this.$parent.queryList();
},
// 搜索专用
handleSearchChange(page = 1, size = 10) {
this.paginationOptions.pageSize = size;
this.paginationOptions.currentPage = page;
this.queryList ? this.queryList() : this.$parent.queryList();
}
}
};

export default table;

写在最后

当前的table组件是针对自己项目的需求封装,兼容了饿了么table大部分的业务场景,随着后期的业务拓展,当前的组件的拓展性也会增强,封装路漫漫,一点点完善吧。