Element Plus二次封装el-table 扩展【表格动态列展示】

前言

el-table二次封装请看 Element Plus二次封装el-table、可编辑表格

效果展示

可通过表单配置来决定哪些列展示或隐藏
在这里插入图片描述
在这里插入图片描述

代码

table.ts

const columnsData: any = [
    {
    
    
        prop: 'username',
        label: '姓名',
        show: true, // 通过 show 来控制列的展示或隐藏 
    },
    {
    
    
        prop: 'age',
        label: '性别',
        align: 'center',
        type: 'status',
        option: {
    
    
            '1': '男',
            '2': '女'
        },
        width: 80,
        show: true
    },
    {
    
    
        prop: 'phone',
        label: '手机号',
        align: 'center',
        width: 150,
        show: true
    },
    {
    
    
        prop: 'email',
        label: '邮箱',
        align: 'center',
        width: 180,
        show: true
    }
]

index.vue


<template>
    <div class="role">
    	<!-- 只添加了el-popover这些代码 -->
    	<el-popover placement="bottom" title="表格配置" :width="200" trigger="click">
            <div v-for="(item, index) in columns" :key="index">
                <el-checkbox v-model="item.show" :label="item.label" :true-label="true" :false-label="false" />
            </div>
            <template #reference>
                <el-button :icon="Operation"></el-button>
            </template>
        </el-popover>
        
    	<!-- LTable是之前封装的,不懂的可以看上面的链接 -->
        <LTable :tableModule="tableModule"  :tableChildren="1">
            <template #event>
                <el-table-column align="center" fixed="right" label="操作" width="120">
                    <template slot-scope="scope" #default="scope">
                        <el-button @click="userDelete(scope)">删除</el-button>
                    </template>
                </el-table-column>
            </template>
        </LTable>
    </div>
</template>
<script setup lang="ts">
import {
      
       Operation } from '@element-plus/icons-vue' // Icon图标
</script>

LTable.vue

<!-- 最后修改之前封装的组件 -->
<template>
    <div class="l-table">
        <!-- 表格 -->
        <el-table :data="props.tableModule.dataList" border height="100%" style="width: 100%; overflow-y: scroll"
            v-loading="props.tableModule.loading" @selection-change="props.tableModule.selectChange"
            :row-class-name="tableRowClassName" :cell-class-name="tableCellClassName" @cell-dblclick="cellDblClick">
            <el-table-column type="selection" width="50" align="center" />
            <!-- v-for 循环拿到了外层,在 el-table-column 判断 item.show 就可以了 -->
            <template v-if="tableChildren == '1'" v-for="(item, index) in props.tableModule.columns">
                <el-table-column :prop="item.prop"
                    :label="item.label" :align="item.align || 'left'" :width="item.width" :min-width="item.min_width"
                    :fixed="item.fixed" v-if="item.show">
                    <template slot-scope="scope" #default="scope">
                        <div v-if="item.type == 'switch'">
                            <el-switch v-model="scope.row[item.prop]" :active-value="item.activeValue"
                                :inactive-value="item.inactiveValue" @change="props.tableModule.switchChange(scope.row)">
                            </el-switch>
                        </div>
                        <div v-else-if="item.type == 'status'">
                            <el-tag :type="item.color ? item.color[scope.row[item.prop]] : ''">{
   
   {
                                props.tableModule.fieldChange(scope.row[item.prop], item.option) }}</el-tag>
                        </div>
                        <div v-else-if="item.type == 'image'">
                            <el-image style="width: 60px; height: 60px" :src="scope.row[item.prop]"
                                :preview-src-list="[scope.row[item.prop]]">
                            </el-image>
                        </div>
                        <div v-else-if="item.type == 'time'">{
   
   { formatDate(scope.row[item.prop]) }}</div>
                        <div v-else-if="item.isEdit">
                            <el-input v-model="scope.row[item.prop]" :placeholder="'请输入' + item.label"
                                @blur="inputBlur(scope.row)" autofocus ref="inputRef"
                                v-if="scope.row['index'] == rowIndex && scope.column['index'] == columnIndex" />
                            <div v-else>{
   
   { scope.row[item.prop] }}</div>
                        </div>
                        <div v-else>{
   
   { scope.row[item.prop] }}</div>
                    </template>
                </el-table-column>
            </template>
            <template v-else-if="tableChildren == '2'">
                <el-table-column v-for="(one, index) in props.tableModule.columns" :key="index" :label="one.label">
                    <el-table-column v-for="item in props.tableModule.columns[index].children" :key="item.prop"
                        :prop="item.prop" :label="item.label" :align="item.align || 'left'" :width="item.width"
                        :min-width="item.min_width" :fixed="item.fixed">
                        <template slot-scope="scope" #default="scope">
                            <div v-if="item.type == 'switch'">
                                <el-switch v-model="scope.row[item.prop]" :active-value="item.activeValue"
                                    :inactive-value="item.inactiveValue"
                                    @change="props.tableModule.switchChange(scope.row)">
                                </el-switch>
                            </div>
                            <div v-else-if="item.type == 'status'">
                                <el-tag :type="item.color ? item.color[scope.row[item.prop]] : ''">{
   
   {
                                    props.tableModule.fieldChange(scope.row[item.prop], item.option) }}</el-tag>
                            </div>
                            <div v-else-if="item.type == 'image'">
                                <el-image style="width: 60px; height: 60px" :src="scope.row[item.prop]"
                                    :preview-src-list="[scope.row[item.prop]]">
                                </el-image>
                            </div>
                            <div v-else-if="item.type == 'time'">{
   
   { formatDate(scope.row[item.prop]) }}</div>
                            <div v-else-if="item.isEdit">
                                <el-input v-model="scope.row[item.prop]" :placeholder="'请输入' + item.label"
                                    @blur="inputBlur(scope.row)" autofocus ref="inputRef"
                                    v-if="scope.row['index'] == rowIndex && scope.column['index'] == columnIndex" />
                                <div v-else>{
   
   { scope.row[item.prop] }}</div>
                            </div>
                            <div v-else>{
   
   { scope.row[item.prop] }}</div>
                        </template>
                    </el-table-column>
                </el-table-column>
            </template>
            <slot name="event"></slot>
        </el-table>
        <div class="l-pages">
            <!-- 分页 -->
            <el-pagination :current-page="props.tableModule.pages.page" :page-size.sync="props.tableModule.pages.limit"
                :page-sizes="pageSizes" :layout="layout" :total="props.tableModule.pages.total"
                @size-change="props.tableModule.sizeChange" @current-change="props.tableModule.currentChange" />
        </div>
    </div>
</template>

二级表头

二级表头其实没什么说的,嵌套一次循环就可以了

table.ts

const columnsData: any = [
    {
    
    
        label: '基础信息',
        show: true, // 外层加了show属性
        children: [
            {
    
    
                prop: 'menuPowerName',
                label: '菜单权限名称',
                min_width: 120,
                fixed: true,
                show: true
            },
            {
    
    
                prop: 'menuPowerMark',
                label: '菜单权限标识',
                align: 'center',
                width: 180,
                fixed: true,
                show: true
            },
            {
    
    
                prop: 'menuName',
                label: '所属菜单名称',
                align: 'center',
                width: 180,
                fixed: true,
                show: true
            },
        ]
    },
    {
    
    
        label: '时间',
        show: true,
        children: [
            {
    
    
                prop: 'createDate',
                label: ' 创建时间',
                align: 'center',
                type: 'time',
                width: 180,
                show: true
            }
        ]
    }
]

index.vue

<!-- 嵌套一次循环 -->
<el-popover placement="bottom" title="表格配置" :width="200" trigger="click">
    <div v-for="(item, index) in columns" :key="index">
        <el-checkbox v-model="item.show" :label="item.label" :true-label="true" :false-label="false" />
        <div style="margin-left: 20px;" v-for="(cItem, cIndex) in item.children" :key="cIndex">
            <el-checkbox v-model="cItem.show" :label="cItem.label" :true-label="true"
                :false-label="false" />
        </div>
    </div>
    <template #reference>
        <el-button :icon="Operation"></el-button>
    </template>
</el-popover>

LTable.vue

<!-- 最后修改之前封装的组件 -->
<template>
    <div class="l-table">
        <!-- 表格 -->
        <el-table :data="props.tableModule.dataList" border height="100%" style="width: 100%; overflow-y: scroll"
            v-loading="props.tableModule.loading" @selection-change="props.tableModule.selectChange"
            :row-class-name="tableRowClassName" :cell-class-name="tableCellClassName" @cell-dblclick="cellDblClick">
            <el-table-column type="selection" width="50" align="center" />
            <!-- v-for 循环拿到了外层,在 el-table-column 判断 item.show 就可以了 -->
            <template v-if="tableChildren == '1'" v-for="(item, index) in props.tableModule.columns">
                <el-table-column :prop="item.prop"
                    :label="item.label" :align="item.align || 'left'" :width="item.width" :min-width="item.min_width"
                    :fixed="item.fixed" v-if="item.show">
                    <template slot-scope="scope" #default="scope">
                        <div v-if="item.type == 'switch'">
                            <el-switch v-model="scope.row[item.prop]" :active-value="item.activeValue"
                                :inactive-value="item.inactiveValue" @change="props.tableModule.switchChange(scope.row)">
                            </el-switch>
                        </div>
                        <div v-else-if="item.type == 'status'">
                            <el-tag :type="item.color ? item.color[scope.row[item.prop]] : ''">{
   
   {
                                props.tableModule.fieldChange(scope.row[item.prop], item.option) }}</el-tag>
                        </div>
                        <div v-else-if="item.type == 'image'">
                            <el-image style="width: 60px; height: 60px" :src="scope.row[item.prop]"
                                :preview-src-list="[scope.row[item.prop]]">
                            </el-image>
                        </div>
                        <div v-else-if="item.type == 'time'">{
   
   { formatDate(scope.row[item.prop]) }}</div>
                        <div v-else-if="item.isEdit">
                            <el-input v-model="scope.row[item.prop]" :placeholder="'请输入' + item.label"
                                @blur="inputBlur(scope.row)" autofocus ref="inputRef"
                                v-if="scope.row['index'] == rowIndex && scope.column['index'] == columnIndex" />
                            <div v-else>{
   
   { scope.row[item.prop] }}</div>
                        </div>
                        <div v-else>{
   
   { scope.row[item.prop] }}</div>
                    </template>
                </el-table-column>
            </template>
            <!-- 这里无论循环一级还是二级都需要在template上去写循环 -->
            <template v-else-if="tableChildren == '2'" v-for="(one, index) in props.tableModule.columns">
                <el-table-column :label="one.label" v-if="one.show">
                    <template v-for="item in props.tableModule.columns[index].children">
                        <el-table-column :prop="item.prop" :label="item.label" :align="item.align || 'left'"
                            :width="item.width" :min-width="item.min_width" :fixed="item.fixed" v-if="item.show">
                        	<template slot-scope="scope" #default="scope">
                            	<div v-if="item.type == 'switch'">
                                	<el-switch v-model="scope.row[item.prop]" :active-value="item.activeValue"
                                    :inactive-value="item.inactiveValue"
                                    @change="props.tableModule.switchChange(scope.row)">
                                	</el-switch>
                            	</div>
                            	<div v-else-if="item.type == 'status'">
                                	<el-tag :type="item.color ? item.color[scope.row[item.prop]] : ''">{
   
   {
                                    props.tableModule.fieldChange(scope.row[item.prop], item.option) }}</el-tag>
                            	</div>
                            	<div v-else-if="item.type == 'image'">
                                	<el-image style="width: 60px; height: 60px" :src="scope.row[item.prop]"
                                    :preview-src-list="[scope.row[item.prop]]">
                                	</el-image>
                            	</div>
                            	<div v-else-if="item.type == 'time'">{
   
   { formatDate(scope.row[item.prop]) }}</div>
                            	<div v-else-if="item.isEdit">
                                	<el-input v-model="scope.row[item.prop]" :placeholder="'请输入' + item.label"
                                    @blur="inputBlur(scope.row)" autofocus ref="inputRef"
                                    v-if="scope.row['index'] == rowIndex && scope.column['index'] == columnIndex" />
                                	<div v-else>{
   
   { scope.row[item.prop] }}</div>
                            	</div>
                            	<div v-else>{
   
   { scope.row[item.prop] }}</div>
                        	</template>
                    	</el-table-column>
                	</template>
                </el-table-column>
            </template>
            <slot name="event"></slot>
        </el-table>
        <div class="l-pages">
            <!-- 分页 -->
            <el-pagination :current-page="props.tableModule.pages.page" :page-size.sync="props.tableModule.pages.limit"
                :page-sizes="pageSizes" :layout="layout" :total="props.tableModule.pages.total"
                @size-change="props.tableModule.sizeChange" @current-change="props.tableModule.currentChange" />
        </div>
    </div>
</template>

这样就完成了,给大家看下效果
在这里插入图片描述
感谢观看~

猜你喜欢

转载自blog.csdn.net/m0_67584973/article/details/131186675
今日推荐