用iview的表格方式封装element中的table表格和分页
程序员文章站
2024-03-21 17:41:04
...
因为经常做后台项目,需要使用表格分页,UI组件一直用的element,但是这个表格用起来感觉很乱,就像在写原生的table,而不像一个组件,没有iview的表格功能那么好用,iview表格是用一个data数据跟columns参数 就可以驱动整个表格,需要配置啥只用在columns里更改即可,方便完美,所以项目中一直加载了两个ui库,按需加载了iview的表格,其他的全部使用的cnd引入的element,简直不要太难受,所以就抽空,将element的表格按照iview的那种格式封装了一下。 大致是完成了,想要修改添加可自行修改。
放代码:
显示封装的组件代码
<template>
<!-- element的table表格的组件 -->
<div class="list_data">
<div class="list_table">
<el-table ref='tableBox' :size='size' :data="data" :border='border' :stripe='stripe' :max-height="height?height:null" :highlight-current-row='heightLinght' :show-header='showHeader' :empty-text='emptyText' :show-overflow-tooltip='showTooltip' :row-class-name="getRowClass" :cell-class-name='getCellClass' :header-cell-class-name='getHeadClass' @row-click='handRowClick' @selection-change="handleSelectionChange" style='width:100%'>
<!-- 多选框 -->
<el-table-column type="selection" width="55" v-if='multiple'></el-table-column>
<!-- 单选框 -->
<el-table-column width="55" v-if='radio'>
<template slot-scope="scope">
<el-radio v-model="radioValue" :label="scope.row[rowKey]">{{ }}</el-radio>
</template>
</el-table-column>
<!-- 序号 -->
<el-table-column type="index" width="50" :label='indexLabel' v-if='index'></el-table-column>
<!-- 其他数据 -->
<el-table-column v-for='(item,index) in columns' :key='index' :prop="item.key" :label="item.title" :width="item.width" :fixed='item.fixed?item.fixed:null'>
<template slot-scope="{row, column, $index}">
<!-- 如果有插槽内容,则显示插槽 -->
<template v-if="item.slot">
<slot :name="item.slot" :row="row" :column="column" :index="$index"></slot>
</template>
<!-- 如果没有,则显示默认的数据 -->
<template v-else>
{{row[item.key]}}
</template>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页功能 -->
<div class="list_page" v-if='page'>
<el-pagination :current-page="currentPage" :page-size="pageSize" :total="total" :page-sizes="pageSizeArr" :layout="layout" :pager-count="pagerCount" :background='background' :small='small' :hide-on-single-page='hideOn' @current-change="handleCurrentChange" @size-change="handleSizeChange"></el-pagination>
</div>
</div>
</template>
<script>
/*
@selectChange 暴露出去一个方法 返回的是单选或者多选的数据
@pageChange 分页的改变 不管是当前页数的改变 还是每页显示数量的改变都会触发 返回一个对象
{
currentPage: '',
pageSize: ''
}
*/
export default {
// 下面这些就是所有的设置的参数
props: {
// 表格的数据 必传
data: {
type: Array,
default: [],
},
// 表格的表头内容和对应的字段,还有是否定位 宽度等 必传
/*
columns:[
{
title: "名称",//表头
key: "name",//对应的参数
fixed:'left',//是否定位
width:70,//宽度
slot:'',//slot是作为插槽来用,自定义内容标签
}
]
*/
columns: {
type: Array,
default: []
},
// 表格是否显示序号 默认为显示
index: {
type: Boolean,
default: true,
},
// 序号的标题设置
indexLabel: {
type: String,
default: '序号'
},
// 表格是否显示边框 默认为显示
border: {
type: Boolean,
default: true,
},
// 表格是否显示斑马条纹的颜色 默认为显示
stripe: {
type: Boolean,
default: true,
},
// Table 的尺寸 medium / small / mini 默认为 medium
size: {
type: String,
default: 'medium'
},
// 是否显示表头, 默认为显示
showHeader: {
type: Boolean,
default: true,
},
// 是否高亮当前点击行 默认为false
heightLinght: {
type: Boolean,
default: false,
},
// 默认情况下若内容过多会折行显示,为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。
showTooltip: {
type: Boolean,
default: false,
},
// 表格最大高度,是需要固定表头的时候设置这个值 默认为空
height: {
type: [String, Number],
default: ''
},
// 数据的唯一值,默认为id,在多选点击行选中 和 单选时 单选按钮选中时 需要使用这个值
rowKey: {
type: String,
default: 'id',
},
// 表格是否需要作为单选,如果为单选,则会显示单选按钮 并返回一个方法来接受选择的数据 如果需要开启 则需要传递 rowKey 这个唯一值
radio: {
type: Boolean,
default: false,
},
// 是否需要作为多选模式,默认为false,如果多选,则会显示多选框,并返回一个方法来接受选择的数据
multiple: {
type: Boolean,
default: false,
},
// 这个主要是为多选时服务,是否在多选时点击行就选中数据,element默认是只能选中多选框才能选中数据,如果开启,则需要传递下面的rowKey,如果唯一值为id,则不需要,默认为id,
rowSelect: {
type: Boolean,
default: false,
},
// 当没有数据时,需要展示的文字提示
emptyText: {
type: String,
default: '暂无数据'
},
// 给某一行添加class添加样式 Function(row, rowIndex)/String
rowClassName: [String, Function],
// 列的className的回调方法 Function(row, column, rowIndex, columnIndex)/String
cellClassName: [String, Function],
// 表头单元格的 className 的回调方法, Function({row, rowIndex})/String
headClassNmae: [String, Function],
// 是否显示分页,默认为显示
page: {
type: Boolean,
default: true,
},
// 当前显示的页数
currentPage: {
type: Number,
default: 1,
},
// 每页显示的数量
pageSize: {
type: Number,
default: 20,
},
// 总条数
total: {
type: Number,
default: 0,
},
// 页码按钮的数量,当总页数超过该值时会折叠,大于等于 5 且小于等于 21 的奇数
pagerCount: {
type: Number,
default: 5,
},
//每页显示个数选择器的选项设置
pageSizeArr: {
type: Array,
default: [10, 20, 30, 40, 50, 100],
},
// 是否使用小型分页样式 默认为false
small: {
type: Boolean,
default: false,
},
// 是否为分页按钮添加背景色 默认为true
background: {
type: Boolean,
default: true,
},
// 只有一页时是否隐藏 默认为false
hideOn: {
type: Boolean,
default: false,
},
layout: {
type: String,
default: 'prev, pager, next,sizes, total,jumper'
}
},
data() {
return {
radioValue: '',//单选按钮绑定的值
selectList: [],//选中的值
};
},
computed: {
},
watch: {
},
methods: {
// 获取行的classname
getRowClass({ row, rowIndex }) {
var rowClass = this.rowClassName;
if (typeof rowClass === 'string') {
return rowClass;
} else if (typeof rowClass === 'function') {
return rowClass(row, rowIndex)
}
},
// 获取列的className
getCellClass({ row, column, rowIndex, columnIndex }) {
var cellClass = this.cellClassName;
if (typeof cellClass === 'string') {
return cellClass;
} else if (typeof cellClass === 'function') {
return cellClass(row, column, rowIndex, columnIndex)
}
},
// 获取表头的className
getHeadClass({ row, rowIndex }) {
var headClass = this.headClassNmae;
if (typeof headClass === 'string') {
return headClass;
} else if (typeof headClass === 'function') {
return headClass(row, rowIndex)
}
},
// 点击多选框时的数据
handleSelectionChange(val) {
this.selectList = val;
this.$emit('selectChange', this.selectList)
},
// 某一行被点击时
handRowClick(row, column) {
// 如果为单选时
if (this.radio) {
this.selectList = [];
this.radioValue = row[this.rowKey];//将选中的值赋值用于单选按钮的选中
this.$refs.tableBox.setCurrentRow(row);//单选时 element提供了一个方法 来使选中的高亮
this.selectList.push(row);
this.$emit('selectChange', this.selectList)
}
//如果为多选时,需要点击行来选中数据 rowSelect为true , rowKey为列表唯一值
if (this.multiple && this.rowSelect && this.rowKey) {
// 先判断点击的数据是否已在选中数据中存在 不过需要一个列表的唯一值来判断 默认为id
let index = this.selectList.findIndex(item => {
return item[this.rowKey] == row[this.rowKey]
})
if (index == -1) {
// 如果未存在,设置已选状态
this.$refs.tableBox.toggleRowSelection(row, true); //设置复选框为选中状态
} else {
// 如果已存在,设置未选状态
this.$refs.tableBox.toggleRowSelection(row, false); //设置复选框为未选状态
}
}
},
// 选取页数
handleCurrentChange(val) {
this.currentPage = val;
this.$emit('pageChange', {
currentPage: this.currentPage,
pageSize: this.pageSize
})
},
// 选取每页显示的数量
handleSizeChange(val) {
var num = this.currentPage * val;
if (this.total < num && this.total > 0) {
this.currentPage = Math.ceil(this.total / val)
}
this.pageSize = val;
this.$emit('pageChange', {
currentPage: this.currentPage,
pageSize: this.pageSize
})
},
},
mounted() {
},
};
</script>
<style scoped lang="less">
// 这个样式是根据自己项目里需要写的,可以自己更改,用的flex
.list_data {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
padding-bottom: 50px;
.list_table {
flex: 1;
overflow: auto;
.el-table {
.el-table__body-wrapper {
overflow: auto;
// 表格的滚动条的样式
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
&::-webkit-scrollbar-thumb {
background: #bfbfbf;
border-radius: 10px;
}
}
}
&::-webkit-scrollbar {
width: 8px;
height: 5px;
}
&::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
&::-webkit-scrollbar-thumb {
background: #bfbfbf;
border-radius: 10px;
}
// &::-webkit-scrollbar-thumb:hover {
// background: #2789ff;
// }
}
.list_page {
width: 100%;
position: absolute;
left: 0;
bottom: 0;
background: #fff;
text-align: right;
}
}
.list_table /deep/.el-table tr {
color: #424142;
font-size: 14px;
font-family: "黑体";
th {
text-align: center;
font-weight: bold;
color: #666;
}
td {
text-align: center;
line-height: 1.3;
}
}
</style>
组件代码已完成 自定义插槽是用的slot,没有用iview那样的render函数,感觉那样写起来好费劲。
下面的就是组件的使用
<template>
<div class="list_box">
<v-table :data='tableData' :columns='columns' radio :rowClassName='tableRowClassName' @selectChange='selectChange($event)' @pageChange='pageChange($event)'>
<!-- 这地方是自定义的一个插槽 slot对应的colums定义的slot参数, slot-scope="scope" 必须要有 是接收组件返回的每行的数据-->
<div slot='caozuo' slot-scope="scope">
<button @click.stop="slotClick(scope)">点击</button>
</div>
</v-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
id: 1,
},
{
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄',
id: 2,
},
{
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄',
id: 3,
},
{
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄',
id: 4,
},
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
id: 5,
},
{
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄',
id: 6,
},
{
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄',
id: 7,
},
{
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄',
id: 8,
},
],
columns: [
{
title: "日期",
key: "date",
width: 180,
},
{
title: "姓名",
key: "name",
width: 180,
},
{
title: "地址",
key: "address",
},
{
title: "操作",
slot: 'caozuo',
width: 300,
}
],
};
},
methods: {
// 这个是自定义按钮点击返回的数据
slotClick(obj) {
console.log(obj);
// {row: {…}, column: {…}, index: 2}
},
// 这个是表格多选返回的数据
selectChange(data) {
console.log(data);
},
// 这个是表格的rowClassName参数添加class 其他cellClassName 跟 headClassNmae 一样 ,
tableRowClassName(row, rowIndex) {
// 这里返回的class名自己在下面定义好样式
if (rowIndex === 1) {
return 'warning-row';
} else if (rowIndex == 3) {
return 'success-row';
}
},
// 这个是分页的改变返回的内容
pageChange(obj) {
console.log(obj);
//{currentPage: 1, pageSize: 30}
}
},
mounted() {
},
};
</script>
<style scoped lang="less">
// 这里就是 rowClassName 自定义的class的样式
.list_box /deep/.el-table .warning-row td {
background: oldlace;
}
.list_box /deep/.el-table .success-row td {
background: #f0f9eb;
}
</style>
到这就完事了,大概就这样了,刚写完,还有需要优化的地方,可自行修改自己需要的
下面放一张使用图