vue开发札记

238 阅读1分钟

elementUI 表格组件二次开发

组件使用环境说明 vue2.6 + jsx 基于 es6

demo

<picc-table 
:column="includeTable" 
:data="includeData" height="auto"
:selection="true" 
:number="true" 
:showPagination="false" 
:single="true">
    <template slot="action" slot-scope="{ scope }">
          <el-button @click="eventClickDelete(scope)">删除</el-button>
          <el-button><a href="http://www.baidu.com" target="_bank">下载</a></el-button>
          </template>
                                   
 </picc-table>
  

props 说明

@name 表格组件
@param {data} JSON  数据
@param {column} object const tableColumn = [{prop: "contractId",label: "合同ID"},{ prop: "action",label: "操作", slot: "action"}];
@param {showPagination} boolean 是否显示分页
@param {pagination} listQuery: { total: 0, page: 1,limit: 10,importance: undefined, title: undefined, type: undefined, sort: "+id" }
@param {selectable} function 判断是否能选中 
@param {number} boolean 是否显示行号
@param {single} Boolean 是否单选
@event onChange  分页请求数据
@event selected 多选
@event currentSelect 单选 

组件源码

/**
 * @template <picc-table :data="tableData" :column="tableColumn" :pagination="listQuery" @onChange="onPageChange">
            <template slot="action" slot-scope="scope">
                <el-button type="text" @click="onAddContract(scope)">
                    添加
                </el-button>
            </template>
    </picc-table>
    @name 表格组件
    @param {data} JSON  数据
    @param {column} object const tableColumn = [{prop: "contractId",label: "合同ID"},{ prop: "action",label: "操作", slot: "action"}];
    @param {showPagination} boolean 是否显示分页
    @param {pagination} listQuery: { total: 0, page: 1,limit: 10,importance: undefined, title: undefined, type: undefined, sort: "+id" }
    @param {selectable} function 判断是否能选中 
    @param {number} boolean 是否显示行号
    @param {single} Boolean 是否单选
    @event onChange  分页请求数据
    @event selected 多选
    @event currentSelect 单选 

 */
import Pagination from "@/components/Pagination";
import "./piccTable.scss";
let selectMap = new Map();
export default {
    name: "picc-table",
    comments: { [Pagination.name]: Pagination },
    props: {
        data: {
            type: Array,
            default() {
                return [];
            } // 数据
        },
        column: {
            type: Array,
            defualt() {
                return [];
            }
        },
        // 翻页信息
        pagination: {
            type: Object,
            default() {
                return {
                    total: 100,
                    page: 0,
                    limit: 20,
                    pageNo: 0
                };
            }
        },
        selection: { type: Boolean, default: false },
        // 显示翻页
        showPagination: {
            type: Boolean, default: true
        },
        // 返回false 或 true 判断选中
        selectable: { type: Function, default() { return new Function() } },
        // 高度
        height: { type: String, default: "400" },
        // 序号
        number: { type: Boolean, defualt: false },
        single: { type: Boolean, default: false },

    },
    data() {
        return {
            radio: ""
        };
    },
    mounted() {
        this.init();
    },
    methods: {
        init() {
            selectMap = new Map();

            this.$refs.table.clearSelection();
        },
        // TODO: 创建表头
        createColumn() {

            let children = ({ slot }) => {
                if (slot) {
                    return this.$scopedSlots[slot];
                }
            };

            let col = this.column.map((item = { prop: "", label: "--", align: "center" }, ind) => {
                return (
                    <el-table-column prop={item.prop} label={item.label} show-overflow-tooltip align="center" key={ind} width={item["width"] || "auto"}>
                        {children(item)}
                    </el-table-column>
                );
            });
            // 选择框

            // 序号
            if (this.number) {
                col.unshift(<el-table-column
                    fixed="left"
                    type="index"
                    width="50"
                    label="序号"
                    align="center"
                />)
            }
            // 多选
            if (this.selection && !this.single) {
                col.unshift(<el-table-column
                    fixed="left"
                    type="selection"
                    width="50"
                    selectable={this.selectable}
                />)
            }
            // // 单选
            if (this.single) {
                col.unshift(<el-table-column
                    fixed="left"
                    width="50"
                    label=""
                    {...{
                        scopedSlots: {
                            default: (scope) => {
                                return <el-radio class="singleRadio" label={scope.row.id} value={this.radio} />
                            }
                        }
                    }}
                >

                </ el-table-column>)
            }
            return col;
        },

        // TODO: 翻页事件
        EventOnPagination(data) {
            let pagination = Object.assign({ ...this.pagination }, { ...data });
            this.$emit("onChange", pagination);
        },
        // TODO: sync page
        SyncEventlimit(data) {
            // let limit = { limit: data };
            // this.EventOnPagination(pages);
        },
        // TODO: sync page
        SyncEventpage(data) {
            // let page = { page: data };
            // this.EventOnPagination(page);
        },
        // 设置选中
        setSelected(row) {
            let { pageNo } = this.pagination;

            if (row && row.length) {
                // 判断单选还是多选
               
                selectMap.set(
                    pageNo,
                    row.map((item) => {
                        return item.id;
                    })
                );
            } else {
                selectMap.delete(pageNo);
            }
            this.$emit("selected", selectMap);

        },
        eventSelectionChange() {
            
        },
        eventCurrentChange(val) {
            this.radio = val.id;
            this.$emit('currentSelect', val)
        },
        // 手动选中
        eventSelect(selection) {
            
            this.setSelected(selection);
        },
        // 全选
        eventSelectAll(selection) {
            
            this.setSelected(selection);
        }
    },
    render() {
        let { data, pagination, showPagination, height, single } = this;
        let showPage = () => {
            if (showPagination) {
                return <Pagination
                    total={pagination.total}
                    page={pagination.page}
                    limit={pagination.limit}
                    showHeader={true}
                    {...{
                        on: {
                            "update:limit": this.SyncEventlimit,
                            "update:page": this.SyncEventpage,
                            pagination: this.EventOnPagination
                        }
                    }}
                />
            }
        }
        return (
            <article class='picc-table'>
                <el-table
                    data={data} fit border empty-text="暂无数据" style="width: 100%" height={height}
                    highlightCurrentRow={single}
                    class={{ "single": true }}
                    {...{
                        ref: "table",
                        on: {
                            "select": this.eventSelect,
                            "select-all": this.eventSelectAll,
                            "selection-change": this.eventSelectionChange,
                            "current-change": this.eventCurrentChange
                        }
                    }}


                >
                    {this.createColumn()}
                </el-table>
                {showPage()}
            </article >
        );
    }
};

翻页组件源码 @/components/Pagination

此组件只是为了配合翻页使用

<template>
    <div v-if="total > 0" :class="{ hidden: hidden }" class="pagination-container">
        <el-pagination
            :background="background"
            :current-page.sync="currentPage"
            :page-size.sync="pageSize"
            :layout="layout"
            :page-sizes="pageSizes"
            :total="total"
            v-bind="$attrs"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
        />
    </div>
</template>

<script>
import { scrollTo } from "@/utils/scroll-to";
export default {
    name: "Pagination",
    props: {
        total: {
            required: true,
            type: Number
        },
        page: {
            type: Number,
            default: 1
        },
        limit: {
            type: Number,
            default: 10
        },
        pageSizes: {
            type: Array,
            default() {
                return [10, 20, 30, 50];
            }
        },
        layout: {
            type: String,
            default: "total, sizes, prev, pager, next, jumper"
        },
        background: {
            type: Boolean,
            default: true
        },
        autoScroll: {
            type: Boolean,
            default: true
        },
        hidden: {
            type: Boolean,
            default: false
        }
    },
    computed: {
        currentPage: {
            get() {
                return this.page;
            },
            set(val) {
                this.$emit("update:page", val);
            }
        },
        pageSize: {
            get() {
                return this.limit;
            },
            set(val) {
                this.$emit("update:limit", val);
            }
        }
    },
    methods: {
        handleSizeChange(val) {
            this.$emit("pagination", { page: this.currentPage, limit: val });
            if (this.autoScroll) {
                scrollTo(0, 800);
            }
        },
        handleCurrentChange(val) {
            this.$emit("pagination", { page: val, limit: this.pageSize });
            if (this.autoScroll) {
                scrollTo(0, 800);
            }
        }
    }
};
</script>

<style scoped>
.pagination-container {
    background: #fff;
    padding: 32px 16px;
}
.pagination-container.hidden {
    display: none;
}
</style>

为了隐藏单选时label标签写了些scss, import "./piccTable.scss";

.single{

   // 单选
   .singleRadio{
    .el-radio__label{
        display: none;
    }
} 
}