前言
当前项目基于vue2.0+elementui来实现的,所以简单封装一个表格支持render函数来自定义渲染;
内容
custom-column
封装自定义列的组件
var customColumn = { functional: true, render: (h, data) => { const params = { row: data.props.row, column: data.props.prop, render: data.props.render, }; return params.render ? params.render(h, params.row) : h("span", params.row[params.column]); }, };
render
引用时的写法
{ label: "主体资质状态", prop: "status", align: "center", render: (h, row) => { return h( "el-tag", { props: { type: TIKTOK_QUA_COLOR[row.status], }, }, TIKTOK_QUA_STATUS[row.status] ); }, },
ExpandTable
完整的表单组件,同理基于封装的render,这里的组件可以进一步的进行优化,比如将
操作
列表中的按钮,使用render来自定义;
<template> <div class="app-container"> <!-- 查询表单 --> <el-form :inline="true" :model="formData" ref="ruleForm" v-if="formItems.length" > <el-form-item v-for="item in formItems" :label="item.label" :key="item.name" > <component :is="item.type" :type="item.range" :value-format="item.valueFormat" :start-placeholder="item.startPlaceholder" :end-placeholder="item.endPlaceholder" v-model="formData[item.name]" :placeholder="item.placeholder" @keyup.enter.native="submitForm" > <component v-for="(els, i) in item.els" :key="i" :is="els.type" :slot="els.slot" v-model="formData[els.name]" class="input-width" > <el-option v-for="op in els.options" :key="op.value" :label="op.label" :value="op.value" > </el-option> </component> <el-option v-for="op in item.options" :key="op.value" :label="op.label" :value="op.value" > </el-option> </component> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm">查询</el-button> <el-button @click="resetForm">重置</el-button> <el-button v-if="tableConfig.export" @click="handleExport"> 导出 </el-button> <a id="downlink" /> </el-form-item> </el-form> <!-- 动态表格 --> <el-button v-if="tableConfig.add.status" type="primary" class="margin-b15" @click="handleOperateEvent(tableConfig.add.value)" > {{ tableConfig.add.label }} </el-button> <el-table :data="data" border fit highlight-current-row style="width: 100%" :max-height="tableHeight" > <el-table-column v-for="column in columns" :type="column.type" :key="column.prop" :prop="column.prop" :label="column.label" :fixed="column.fixed" :width="column.width" :align="column.align" > <template scope="scope"> <!-- 自定义render --> <custom-column :render="column.render" :row="scope.row" :prop="column.prop" /> </template> </el-table-column> <el-table-column v-if="tableConfig.op.status" label="操作" align="center" fixed="right" > <template slot-scope="scope"> <el-link v-for="els in tableConfig.op.items" :key="els.value" :type="els.type" class="margin-r15" @click="handleOperateEvent(els.value, scope.row)" > {{ els.label }} </el-link> </template> </el-table-column> </el-table> <!-- 分页 --> <v-page style="margin-top: 15px" :page="page" @onChangePage="handlePageChange" /> </div> </template> <script> var customColumn = { functional: true, props: { row: Object, render: Function, prop: String, }, render: (h, data) => { const params = { row: data.props.row, column: data.props.prop, render: data.props.render, }; return params.render ? params.render(h, params.row) : h("span", params.row[params.column]); }, }; export default { props: { formItems: { type: Array, default: () => [], }, data: Array, columns: Array, page: Object, tableConfig: Object, }, components: { customColumn }, data() { return { formData: {}, tableHeight: 600, }; }, created() { if (window) { this.tableHeight = window.innerHeight - 320; if (this.tableHeight < 300) this.tableHeight = 300; } }, methods: { handleExport() { this.$emit("export"); }, submitForm() { this.$emit("search", this.formData); }, resetForm() { this.formData = {}; this.$emit("search", this.formData); }, handlePageChange(data) { this.$emit("page", data); }, handleOperateEvent(type, data) { this.$emit("operate", type, data); }, }, }; </script> <style lang="scss" scoped> .margin-r15 { margin-right: 15px; } .margin-b15 { margin-bottom: 15px; } .input-width { width: 88px !important; } </style>
使用
引用组件使用,因为组件直接在main.js中注册了,所以直接使用了
<template> <div class="app-container"> <!-- 表格 --> <v-ExpandTable :data="tableData" :columns="columns" :form-items="formItems" :page="page" :table-config="tableConfig" @search="handleSearch" @page="handlePageChange" @export="handleExport" @operate="handleOperateEvent" /> </div> </template> <script> import { TIKTOK_QUA_OPTIONS, TIKTOK_QUA_COLOR, TIKTOK_QUA_STATUS, } from "@/utils/data"; import { getQualificationList } from "@/api/dy-compete/qualification"; export default { data() { return { searchForm: {}, formItems: [ { type: "el-input", label: "用户名称", name: "username", placeholder: "请输入用户名称", }, { type: "el-input", label: "代理商名称", name: "agent_name", placeholder: "请输入代理商名称", }, { type: "el-input", label: "一级代理商名称", name: "first_agent_name", placeholder: "请输入一级代理商名称", }, { type: "el-select", label: "主体资质状态", name: "status", placeholder: "请选择主体资质状态", options: TIKTOK_QUA_OPTIONS, }, { type: "el-select", label: "行业资质状态", name: "industry_qua_status", placeholder: "请选择行业资质状态", options: TIKTOK_QUA_OPTIONS, }, ], tableConfig: { type: "subject", op: { status: true, items: [ { label: "编辑", value: "edit", type: "primary", }, { label: "详情", value: "detail", type: "success", }, ], }, add: { status: true, label: "新增主体资质", value: "add", }, export: true, }, columns: [ { label: "用户名称", prop: "username", align: "center", }, { label: "代理商", prop: "agent_name", align: "center", }, { label: "一级代理商", prop: "first_agent_name", align: "center", }, { label: "主体资质状态", prop: "status", align: "center", render: (h, row) => { return h( "el-tag", { props: { type: TIKTOK_QUA_COLOR[row.status], }, }, TIKTOK_QUA_STATUS[row.status] ); }, }, { label: "行业资质状态", prop: "industry_qua_status", align: "center", render: (h, row) => { return h( "el-tag", { props: { type: TIKTOK_QUA_COLOR[row.status], }, }, TIKTOK_QUA_STATUS[row.status] ); }, }, { label: "拒绝理由", prop: "reject_reason", align: "center", }, ], tableData: [], page: {}, }; }, created() { this.getQualificationListInfo(); }, methods: { handleExport() { const head = { username: "用户名", agent_name: "代理商名称", first_agent_name: "一级代理商", status: "主体资质状态", industry_qua_status: "行业资质状态", reject_reason: "拒绝理由", subject: "主体资质", industries: "行业资质", }; this.$downloadFile( this.outFile, "抖音竞价_主体资质信息", head, "/douyin/qualification/subject", this.searchForm, {}, "SUBJECT_QUALIFICATION" ); }, handleSearch(data) { this.searchForm = data; this.getQualificationListInfo(data); }, getQualificationListInfo(params) { getQualificationList(params).then((r) => { this.tableData = r.data.items; this.page = r.data.page; }); }, handlePageChange(data) { this.getQualificationListInfo({ ...data, ...this.searchForm }); }, handleOperateEvent(type, data) { console.log(type, data); }, }, }; </script> <style lang="scss" scoped></style>
渲染效果
学无止境,谦卑而行.