前端组件化之tablePage


该组件大量使用 slot,理想情况下,只需定义列表的对应关系,就可以展示页面

tablePage

在这里插入图片描述

代码分析

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)	//这里用到了【.sync修饰符】
            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 {
    /* width: 100%; */
    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" 	//这里定义 页面title
    	:tableData="tableData" 	//这里传入 列表数据
    	:disPlayFeid="disPlayFeid" 	//这里传入 列表字段信息
    	:selectRowArray.sync="selectRowArray" // 该字段可不传(需要多选框时必传)
    	:currentPage.sync="currentPage" //这里传入 当前页
    	:eachPage.sync="eachPage" //这里传入 每页展示条数
    	:totalPage="totalPage" //这里传入  总条数
    	:loadList="loadList" //这里控制 table loading(可不传)
    	@getList="getList"	// 这里定义 刷新列表的方法
    	selection //该字段可不穿 (需要多选框时必传)
    	tableOpear //该字段可不穿 (需要操作栏时必传)
    >

		// header-right 自定义部分
        <template slot="header-right">
            <p>1111</p>
            <p>2222</p>
        </template>
		


		// content-header-left  自定义部分(这里加入一个搜索框 进行演示)
        <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>



		// content-header-right  自定义部分
        <template slot="content-header-right">
            <p>123</p>
            <p>456</p>
        </template>
		
		
		// table-column-header  自定义部分
		/**
		*  	自定义表头信息时 建议复制下面代码进行修改
		* 	这里可以通过  slot-scope="{ item }"  获取当前行的信息(disPlayFeid字段定义的一样)
		**/
        <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>



		// table-column 自定义部分
		/**
		*	自定义表格信息时 建议复制下面代码进行修改
		*	这里可以通过 slot-scope="{ item, row }"获取相关信息
		*	item:当前行的信息(disPlayFeid 字段定义的一样)
		*	row :当前行的 数据(tableData 字段 传入)
		**/
        <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>
		
		// table-operate 自定义部分
        <template slot="table-operate">
            <el-button>操作</el-button>
            <el-button>操作</el-button>
        </template>
		
		//batch-operate 自定义部分
        <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) {	//这里定义 disPlayFeid 自定中的过滤函数
            let fieldList = {
                1: '数值',
                2: '日期'
            }
            return fieldList[val]
        },
        seatReadOnlyFilter(val) { //这里定义 disPlayFeid 自定中的过滤函数
            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() {
        //this.getList() 该方法主要 [tableData/totalPage] 赋值
    }
}
</script>

<style scoped>
.active {
    color: #229dff;
}
.inactive {
    color: #91a1a9;
}
</style>

属性

参数说明类型可选值默认值是否必选
title页面的标题Stringtrue
tableData列表数据Arraytrue
disPlayFeid列表字段信息true
selectRowArray选中数据Array[][]false
currentPage当前页码Number/String1true
eachPage每页展示条数Number/String10true
totalPage数据总数Number/String0true
loadList列表load状态BooleanBooleanfalsefalse
selection是否展示多选框BooleanBooleanfalsefalse
tableOpear是否展示操作列BooleanBooleanfalsefalse
tableOpearWidth操作列宽度String/Number100false
noHeader是否展示操作列BooleanBooleanfalsefalse
字段说明:
disPlayFeid:[{
   prop: 'read_only',	//table 列 渲染的字段
   label: '是否只读',	//table 列 展示的标题
   filter: this.seatReadOnlyFilter,	//字段展示过滤方法(该字段可不定义)
   width: 100	//table 列 宽度
}]

方法

事件名说明参数
getList刷新列表

slot

slot名说明
header-right自定义该位置内容
content-header-leftt自定义该位置内容
content-header-right自定义该位置内容
table-column-header自定义表头内容(这里举例表头添加提示)
table-columnr自定义表格内容(这里举例添加状态列的小圆点)
table-operater自定义操作列内容
batch-operate自定义该位置内容

说明

  • 需要自定义哪部分,才需要写对应的代码
  • 当表格需要自定义表头和表格数据时,该页面只与数据相关
  • 理想状态下,该页面和一个js文件配合使用,可大大减少开发量,并可保证页面样式的一致性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值