该组件大量使用 slot,理想情况下,只需定义列表的对应关系,就可以展示页面
tablePage
代码分析
tablePage.vue
<template>
<title-page :title="title">
<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">
<el-table-column align="center" type="selection" width="75" fixed="left" v-if="selection"></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
},
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) {
selection.length == this.tableData.length &&
this.tableData.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 |
字段说明:
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文件配合使用,可大大减少开发量,并可保证页面样式的一致性