该组件大量使用 slot,理想情况下,只需定义列表的对应关系,就可以展示页面
tablePage
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200624161748476.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzI3NjkyOA==,size_16,color_FFFFFF,t_70)
代码分析
tablePage.vue
<template>
<title-page :title="title" :noHeader="noHeader">
<template slot="header-right">
<slot name="header-right"></slot>
</template>
<div class="dis-flex flex-dir-column" style="height: 100%;">
<el-col :span="24" class="mar-b-20">
<el-col :span="18" class="dis-flex">
<slot name="content-header-left"></slot>
</el-col>
<el-col :span="6" class="dis-flex flex-justifu-end">
<slot name="content-header-right"></slot>
</el-col>
</el-col>
<div class="bg-fff table flex-auto">
<el-table ref="table" height="100%" @selection-change="selectChange" :data="tableData" stripe tooltip-effect="light" style="width: 100%;" v-loading="loadList" :class="tableClass">
<el-table-column align="center" type="selection" width="75" fixed="left" v-if="selection" :selectable="selectable"></el-table-column>
<el-table-column align="center" width="75" v-els></el-table-column>
<el-table-column v-for="(item, index) in disPlayFeid" :key="index" :prop="item.prop" :label="item.label" :min-width="item.width" header-align="left" align="left" show-overflow-tooltip width="auto">
<template slot="header">
<slot name="table-column-header" v-bind:item="item">
<span>{{item.label}}</span>
</slot>
</template>
<template slot-scope="scope">
<slot name="table-column" :item="item" :row="scope.row">
<span v-if="item.filter">{{item['filter'](scope.row[item.prop])}}</span>
<span v-else>{{scope.row[item.prop]}}</span>
</slot>
</template>
</el-table-column>
<el-table-column label="操作" header-align="left" align="left" fixed="right" :width="tableOpearWidth" v-if="tableOpear">
<template slot-scope="scope">
<slot name="table-operate" :row="scope.row"></slot>
</template>
</el-table-column>
</el-table>
</div>
<div class="blockPaging table-footer" style="line-height: 32px;padding: 14px 10px 14px 24px;">
<div class="operator" v-if="selection">
<el-checkbox v-model="checkedAll" @change="selectedAll">
全选(已选
<span style="color: rgb(230, 164, 65);">{{selectRowArray.length}}</span>
条)
</el-checkbox>
<slot name="batch-operate"></slot>
</div>
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10, 20, 50, 100]" :page-size="eachPage" layout="total, sizes, prev, pager, next" :total="totalPage"></el-pagination>
</div>
</div>
</title-page>
</template>
<script>
import TitlePage from '@/components/page/titlePage.vue'
export default {
name: 'table-page',
props: {
title: {
type: String,
default: 'title'
},
tableData: {
type: Array,
required: true,
default: function() {
return []
}
},
disPlayFeid: {
type: Array,
required: true,
default: function() {
return []
}
},
selectRowArray: {
type: Array,
default: function() {
return []
}
},
currentPage: [Number, String],
eachPage: [Number, String],
totalPage: [Number, String],
loadList: Boolean,
selection: Boolean,
tableOpearWidth: {
type: [String, Number],
default: '100'
},
tableOpear: Boolean,
noHeader: Boolean,
selectable: {
type: Function,
default: function () {
return true
}
},
tableClass: String
},
components: {
'title-page': TitlePage
},
data() {
return {
checkedAll: false
}
},
methods: {
handleSizeChange(val) {
this.$emit('update:eachPage', val)
this.$nextTick(() => {
this.$emit('getList')
})
},
handleCurrentChange(val) {
this.$emit('update:currentPage', val)
this.$nextTick(() => {
this.$emit('getList')
})
},
selectChange(selection) {
const selectableTable = this.tableData.filter(v =>
this.selectable(v)
)
selection.length == selectableTable.length &&
selectableTable.length > 0
? (this.checkedAll = true)
: (this.checkedAll = false)
this.$emit('update:selectRowArray', selection)
},
selectedAll() {
this.$refs.table.toggleAllSelection()
}
}
}
</script>
<style scoped>
.flex-justifu-end {
justify-content: flex-end;
}
.table-footer {
height: 60px;
padding-left: 26px;
padding-right: 15px;
box-sizing: border-box;
background: #fff;
}
.table >>> .el-table__header th {
background: #eceef5;
padding: 12px 0;
}
.table-footer >>> .el-pagination__total,
.table-footer >>> .el-pagination__sizes {
position: static;
}
.operator {
float: left;
position: relative;
color: #ccc;
font-size: 14px;
}
</style>
组件使用
<template>
<table-page
title="我是tableTitle"
:tableData="tableData"
:disPlayFeid="disPlayFeid"
:selectRowArray.sync="selectRowArray"
:currentPage.sync="currentPage"
:eachPage.sync="eachPage"
:totalPage="totalPage"
:loadList="loadList"
@getList="getList"
selection
tableOpear
>
<template slot="header-right">
<p>1111</p>
<p>2222</p>
</template>
<template slot="content-header-left">
<el-input class="input-icon input-34" style="width:300px;" v-model.trim="keywords" placeholder="请输入字段名称进行搜索" maxlength="100" @clear="currentPage=1;getList()" clearable>
<el-button slot="append" icon="el-icon-search" @click="currentPage=1;getList()"></el-button>
</el-input>
</template>
<template slot="content-header-right">
<p>123</p>
<p>456</p>
</template>
<template slot="table-column-header" slot-scope="{ item }">
<span v-if="item.prop == 'read_only'">{{item.label}}<span title="若设置为只读那么:
1、只允许查看字段;
2、不可以修改字段。" class="el-icon-question pointer"></span></span>
<span v-else>{{item.label}}</span>
</template>
<template slot="table-column" slot-scope="{ item, row }">
<div v-if="item.prop == 'status'">
<span :style="row.status == 0?'display:inline-block;width:8px;height:8px;border-radius:50%;background:#38D88F':'display:inline-block;width:8px;height:8px;border-radius:50%;background:#C5D0D5'"></span>
<span style="padding-left:5px;">{{row.status == 0?'启用':'停用'}}</span>
</div>
<span v-else-if="item.filter">{{item['filter'](row[item.prop])}}</span>
<span v-else>{{row[item.prop]}}</span>
</template>
<template slot="table-operate">
<el-button>操作</el-button>
<el-button>操作</el-button>
</template>
<template slot="batch-operate">
<span class="batch mar-l-15 pointer" :class="selectRowArray.length > 0?'active':'inactive'">批量</span>
</template>
</table-page>
</template>
<script>
import TablePage from '@/components/page/tablePage.vue'
export default {
name: 'test-page',
components: {
'table-page': TablePage
},
data() {
return {
tableData: [{
name: 'ceshi1',
type: 1,
read_only: 0,
status: 0,
field_description: 1111111111111
},{
name: 'ceshi2',
type: 2,
read_only: 1,
status: 2,
description: 55555555555555
}],
disPlayFeid: [
{
prop: 'name',
label: '名称',
width: 150
},
{
prop: 'type',
label: '类型',
filter: this.fieldTypeFilter,
width: 100
},
{
prop: 'read_only',
label: '是否只读',
filter: this.seatReadOnlyFilter,
width: 100
},
{
prop: 'status',
label: '启用状态',
width: 100
},
{ prop: 'description', label: '备注', width: 150 }
],
selectRowArray: [],
currentPage: 1,
eachPage: 10,
totalPage: 0,
loadList: false,
keywords: ''
}
},
methods: {
fieldTypeFilter(val) {
let fieldList = {
1: '数值',
2: '日期'
}
return fieldList[val]
},
seatReadOnlyFilter(val) {
let retStr = ''
switch (Number(val)) {
case 0:
retStr = '否'
break
case 1:
retStr = '是'
break
}
return retStr
},
getList() {
this.loadList = true
let postData = {
searchStr: this.keywords,
page: this.currentPage,
per_page: this.eachPage
}
this.gdRequest(
'GET',
`my/url/123/345`,
postData
).then(res => {
if (res.data.code == 200) {
const retData = res.data.data
this.tableData = retData.data
this.totalPage = retData.total
} else {
this.$message.error(res.data.info)
}
this.loadList = false
})
}
},
created() {
}
}
</script>
<style scoped>
.active {
color: #229dff;
}
.inactive {
color: #91a1a9;
}
</style>
属性
参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必选 |
---|
title | 页面的标题 | String | – | – | true |
tableData | 列表数据 | Array | – | – | true |
disPlayFeid | 列表字段信息 | – | – | true | |
selectRowArray | 选中数据 | Array | [] | [] | false |
currentPage | 当前页码 | Number/String | – | 1 | true |
eachPage | 每页展示条数 | Number/String | – | 10 | true |
totalPage | 数据总数 | Number/String | – | 0 | true |
loadList | 列表load状态 | Boolean | Boolean | false | false |
selection | 是否展示多选框 | Boolean | Boolean | false | false |
tableOpear | 是否展示操作列 | Boolean | Boolean | false | false |
tableOpearWidth | 操作列宽度 | String/Number | – | 100 | false |
noHeader | 是否展示操作列 | Boolean | Boolean | false | false |
字段说明: | | | | | |
disPlayFeid:[{
prop: 'read_only',
label: '是否只读',
filter: this.seatReadOnlyFilter,
width: 100
}]
方法
slot
slot名 | 说明 |
---|
header-right | 自定义该位置内容 |
content-header-leftt | 自定义该位置内容 |
content-header-right | 自定义该位置内容 |
table-column-header | 自定义表头内容(这里举例表头添加提示) |
table-columnr | 自定义表格内容(这里举例添加状态列的小圆点) |
table-operater | 自定义操作列内容 |
batch-operate | 自定义该位置内容 |
说明
- 需要自定义哪部分,才需要写对应的代码
- 当表格需要自定义表头和表格数据时,该页面只与数据相关
- 理想状态下,该页面和一个js文件配合使用,可大大减少开发量,并可保证页面样式的一致性