基于 elementUI table 组件封装

714 阅读1分钟

项目需通过 colums 类似的配置实现表单的列配置,但是官方文档没有这个属性,只能封装【封装思路来源于 ivew 源码的 table 组件】

开始

新建一个 test-table.vue

<template>
    <div class="test_table">
        <el-table
            stripe
            border
            fit
            :data="data"
            :columns="columns"
            v-bind="$attrs"
            v-on="$listeners"
        >
            <template v-for="column in columns">
                <!-- eslint-disable-next-line vue/valid-v-for -->
                <el-table-column :label="L(column.label)" v-bind="column">
                    <template #default="scope" v-if="column.render">
                        <expand
                            :rend="column.render"
                            :data="scope"
                            :row="scope.row"
                            :column="column"
                            :index="scope.$index"
                        ></expand>
                    </template>
                </el-table-column>
            </template>
        </el-table>
    </div>
</template>
<script lang='ts'>
import AbpBase from "@/lib/abpbase";
import { Component, Vue, Inject, Prop } from "vue-property-decorator";
import Expand from "./expand";

@Component({ components: { Expand } })
export default class TestTable extends AbpBase {
    @Prop({ required: true }) data;
    @Prop({ required: true }) columns;
}
</script>
<style lang='less' scoped>
@import url("~@/less/common.less");
.test_table {
}
</style>

新建一个 expand.ts(通过 render 函数新建一个组件)

type IParams = {
    row: any;
    index: number | string;
    column?: any;
};

export default {
    name: "TableExpand",
    functional: true,//使组件无状态 (没有 `data`) 和无实例 (没有 `this` 上下文)。他们用一个简单的 `render` 函数返回虚拟节点使它们渲染的代价更小。
    props: {
        row: Object,
        rend: Function,
        index: Number,
        column: {
            type: Object,
            default: null
        },
        data: Object
    },
    // h 就是 createElment 函数
    // ctx 就是存储了一些其他组件传过来的数据如 prop、slots等
    render: (h, ctx: any) => {
        const params: IParams = {
            row: ctx.props.row,
            index: ctx.props.index
        };
        console.log("h", h);
        console.log("ctx", ctx);
        if (ctx.props.column) params.column = ctx.props.column;
        return ctx.props.rend(h, params);
    }
};

测试用例 test.vue

<template>
    <div class="test">
        <test-table :data="data" :columns="columns"></test-table>
    </div>
</template>
<script lang='ts'>
import AbpBase from "@/lib/abpbase";
import { Component, Vue, Inject } from "vue-property-decorator";
import TestTable from "@/components/test-table/index.vue";
@Component({ components: { TestTable } })
export default class Test extends AbpBase {
    data = [
        {
            date: "2016-05-02",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1518 弄"
        },
        {
            date: "2016-05-04",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1517 弄"
        },
        {
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1519 弄"
        },
        {
            date: "2016-05-03",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1516 弄"
        }
    ];
    columns = [
        {
            label: "姓名",
            prop: "name"
        },
        {
            label: "日期",
            prop: "date"
        },
        {
            label: "地址",
            prop: "address",
            render: (h, params) => {                
                return h("span", params.row.prop ? "是" : "否");
            }
        }
    ];
}
</script>
<style lang='less' scoped>
@import url("~@/less/common.less");
.test {
}
</style>