一、Table组件
1、封装Table组件为tableList.vue
文件如下:
javascript
<template>
<!-- 主列表 -->
<el-table :data='tableData' :height='tableHeight' :show-header='showHeader' stripe @expand-change="expandSelect" :expand-row-keys="expands" @cell-click="handleCellClick" empty-text='暂无数据' class='el_tab_alage' :header-cell-style="cellHeaderStyle" :row-key='getRowKeys' @selection-change="handleSelectionChange">
<!-- 单选框 -->
<el-table-column align="center" width="50" label="" v-if="tableSelection.key === true && tableSelection.type === 'radio'">
<template slot-scope="scope">
<el-radio :label="scope.$index" v-model="radio" @change="handleTemplateRow(scope.$index, scope.row)"> </el-radio>
</template>
</el-table-column>
<!-- index索引 -->
<el-table-column label="序号" type="index" width="50" align="center" v-if="tableSelection.key === true && tableSelection.type === 'index'"></el-table-column>
<!-- 多选框 -->
<el-table-column type="selection" width="50" align="center" v-if="tableSelection.key === true && tableSelection.type === 'selection'"></el-table-column>
<!-- 列表表头-->
<el-table-column type="expand" v-if="tableSelection.key === true && tableSelection.type === 'expand'">
<template slot-scope="scope">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item :label="index.label" v-for="(index, item) in tableLabel" :key='item' v-show="index.type === 'expand'">
<span>{{scope.row[index.list]}}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<template v-for="(index, item) in tableLabel">
<el-table-column fit :align='index.tableAlign ? index.tableAlign : "center"' :key='item' :sortable='index.sort' v-if="index.type !== 'expand'" :label="index.label" :width="index.width" :show-overflow-tooltip="index.overflowShow === 'hidden' ? true : false" :prop="index.list">
<template slot-scope="scope">
<!-- 图片 -->
<template v-if="index.type === 'image'">
<el-image v-if="scope.row[index.list] !== ''" style="width: 100px; height: 50px;" :src="scope.row[index.list]">
</el-image>
<div v-else></div>
</template>
<!-- 头像 -->
<template v-else-if="index.type === 'head'">
<el-image v-if="!(scope.row[index.list] === '' || scope.row[index.list] === null)" style="width: 50px; height: 50px;" :src="scope.row[index.list]">
</el-image>
<div v-else></div>
</template>
<!-- 按钮 -->
<template v-else-if="index.type === 'btn'">
<el-button type="text" @click.native.prevent="index.method(scope.row, scope)">
<u>{{scope.row[index.list]}}</u>
</el-button>
</template>
<!-- 下拉 -->
<template v-else-if="index.type === 'select'">
<el-select v-model="scope.row[index.list]" @change="changeType($event, scope.row, item)" size="medium">
<el-option v-for="item in index.options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</template>
<!-- 开关按钮 -->
<template v-else-if="index.type === 'switch'">
<div v-if="index.noSwitch(scope.row)">
<el-switch @change="index.method(scope.row, scope)" v-model="scope.row[index.list]" :inactive-value="index.offValue ? index.offValue : 'off'" :active-value="index.onValue ? index.onValue : 'on'" :inactive-text="index.offText ? index.offText : ''" :active-text="index.onText ? index.onText : ''" :inactive-color="index.offColor ? index.offColor : '#ff4949'" :active-color="index.onColor ? index.onColor : '#13ce66'"></el-switch>
</div>
</template>
<!-- 内容自定义 -->
<template v-else-if="index.type === 'html'">
<div v-html="index.code(scope.row)" class="theHtml"></div>
</template>
<!-- 正常显示 -->
<template v-else>
<!-- {{scope.row[index.list]}} -->
{{scope.row[index.list]?scope.row[index.list]:'-'}}
</template>
</template>
</el-table-column>
</template>
<!-- 正常按钮操作 -->
<el-table-column fit align='center' :label="tableOption.label" :fixed="tableOption.fixed ? tableOption.fixed : false" :width="tableOption.width" v-if="tableOption.value === 0">
<template style="margin-left: 30px;" slot-scope="scope">
<el-button align='right' v-for="(value, item) in tableOption.options" :key='item' v-if="value.show ? value.show(scope.row) : true" :type="value.type ? value.type : 'text'" :style="value.style ? JSON.parse(value.style) : {}" :plain='value.plain ? value.plain : false' :round='value.round ? value.round : false' :size='value.size ? value.size : "medium"' :icon="value.icon" @click.native.prevent="value.method(scope.row, scope)">{{value.label}}
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
data () {
return {
radio: '',
cellHeaderStyle: {
fontSize: "16px",
color: "#606266"
},
expands: [],
getRowKeys (row) {
return row.id
}
}
},
props: {
tableData: {
type: Array,
default: () => { }
},
tableHeight: {
type: Number,
default: () => {
return null
}
},
showHeader: {
type: Boolean,
default: () => {
return true
}
},
tableSelection: {
type: Object,
default: () => {
return {
key: false,
type: '',
detaile: false
}
}
},
tableLabel: {
type: Array,
default: () => { }
},
tableOption: {
type: Object,
default: () => {
return {
value: 999
}
}
}
},
methods: {
handleSelectionChange (val) {
this.$emit('onHandleSelectionChange', val)
},
handleTemplateRow (index, row) {
this.$emit('onHandleTemplateRow', row)
},
changeType (event, row) {
this.$emit('onChangeType', event, row)
},
expandSelect (row, expandedRows) {
const that = this
if (expandedRows.length) {
that.expands = []
if (row) {
that.expands.push(row.id)
}
} else {
that.expands = []
}
},
handleCellClick (row, column, cell, event) {
this.$emit('onHandleCellClick', row, column)
},
}
}
</script>
<style lang="scss" scoped>
.demo-table-expand {
font-size: 0;
}
/deep/ .gutter {
display: inline !important;
}
.el-table thead th {
background-color: #f9f9f9;
}
.demo-table-expand label {
width: 90px !important;
color: #99a9bf !important;
}
.demo-table-expand .el-form-item {
margin-right: 0 !important;
margin-bottom: 0 !important;
width: 50%;
}
.el-table--scrollable-x .el-table__body-wrapper::-webkit-scrollbar {
overflow-x: hidden;
}
.el-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
background-color: rgba(169, 178, 196, 0.3) !important;
}
.el-table__fixed-right {
height: calc(100% - 27px) !important;
}
.el_tab_alage {
border: 1px solid #f0f0f0 !important;
border-bottom: none !important;
margin: {
bottom: 20px !important;
top: 20px !important;
}
.theHtml {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.el-table__row {
.cell {
-webkit-line-clamp: 3 !important;
-webkit-box-orient: vertical !important;
}
.el-button {
margin: {
top: 0 !important;
right: 5px !important;
bottom: 0 !important;
left: 0 !important;
}
}
}
}
</style>
2、使用组件
html
<Table :table-label="tableHeader" v-loading="isSubmitLoading" :table-data="tableData" :table-option="tableOption" :table-selection="tableSelection" @onHandleSelectionChange="handleSelectionChange"></Table>
javascript
import Pagination from "@/components/table/Pagination.vue";
export default {
components: { Table },
data() {
return {
isSubmitLoading: false,
tableHeader:[],
tableData: [],
tableOption: {},
tableSelection: {}
}
},
methods: {
handleSelectionChange() {},
changeStatus() {}
}
}
tableHeader
中每个item
有label
(标题)、type
(类型,分别有image
图片,head
头像,btn
按钮,select
下拉,switch
开关,html
自定义内容等)、list
(对应列内容的字段名)、code: (row) => { return }
(对列数据操作后返回函数)、overflowShow: 'hidden'
(当内容过长被隐藏时显示 tooltip) 等。
如:
javascript
tableHeader:[
{
label: "姓名", type: "html", list: 'name', overflowShow: 'hidden', code: (row) => {
return row.type === 0 ? row.name : row.name + '(管理员)'
}
},{
label: "手机号", type: "html", overflowShow: 'hidden', code: (row) => {
return row.phone === '' || row.phone === null ? '-' : row.phone
}
},{
label: "创建时间", list: 'createTime', overflowShow: 'hidden'
},{
type: "switch",
label: '状态',
list: "state",
offText: '禁用',
onText: '启用',
offValue: "1",
onValue: "0",
noSwitch: (row) => {
return true;
},
method: (row) => {
this.changeStatus(row)
},
},
]
tableOption
中有label
(标题)、width
(对应列的宽度)、options
(操作项,类型为数组,每个item中有label
(标题)、color
(颜色)、type
(类型)、icon
(图标)、method: (row) => {}
(点击后执行的方法)、show:(row) => {}
(显示或者隐藏的判断条件)
如:
javascript
tableOpction: {
label: '操作',
width: '160px',
options: [{
label: '删除',
color: '#DB864E',
type: "text",
icon: "",
method: (row) => {
this.doDelete(row.id);
},
show: (row) => {
return row.type == 1 ? true : false
}
},
{
label: '编辑',
color: '#DB864E',
key: 1,
type: "text",
icon: "",
method: (row) => {
this.doEdit(row.id);
},
}
]
}
tableSelection
配置中有key
(为true时显示)、type
(有index
(显示索引)、selection
(显示多选框)),操作多选框时会触发相应的handleSelectionChange
回调函数,可以拿到已选中的数据。
javascript
data() {
return {
tableSelection: {
key: true,
type: "selection"
}
}
},
methods: {
handleSelectionChange(val) {}
}
二、Pagination组件
1、封装Pagination组件为Pagination.vue
文件如下:
html
<template>
<div class="pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page.page"
:page-sizes="pageSizes"
:page-size="page.limit"
layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
</template>
<script>
export default {
props: {
total: {
type: Number,
default: () => {}
},
pageSizes: {
type: Array,
default: () => {
return [5, 10, 20, 100]
}
}
},
data() {
return {
page: {
page: 1,
limit: 20
}
}
},
methods: {
Page(val) {
this.page.page = val
},
handleSizeChange(val) {
this.page.limit = val
this.$emit('pageChange', this.page)
},
handleCurrentChange(val) {
this.page.page = val
this.$emit('pageChange', this.page)
}
}
}
</script>
<style scoped lang="scss">
.pagination {
float: right;
padding: 1% 4% 2% 0px;
}
</style>
2、使用组件
html
<pagination ref="page" :total="total" @pageChange="pageChange"></pagination>
javascript
import Pagination from "@/components/table/Pagination.vue";
export default {
components: { Pagination },
data() {
return {
total: 0,
pageSize: 20,
currentPage: 1
}
},
methods: {
pageChange (item) {
this.pageSize = item.limit;
this.currentPage = item.page;
this.fetchData(); // 请求数据
},
}
}
total
(总条目数)、pageChange
(pageSize 改变时会触发)