Element Plus Table 表格 单元格内容过长处理

问题描述

用Element Plus框架进行网站的搭建,用到了组件Table,进行列表数据的展示,但由于数据内容过长导致列换行了,自己感觉不美观,想处理下,由于也是才用这个框架对属性没有认真的看,导致走了不少弯路,其实框架本身已经给我们提供了处理办法。

弯路解决(不推荐)

自己参考了一个开源的一个插件:https://github.com/kaysonli/v-fit-columns,此插件可实现el-table-column宽度自适应但基于vue2开发的。但Element Plus框架是基于vue3的所以我对这个源码进行了修改以适应vue3。实际上就是自定义命令v-fit-columns来对列进行扩宽处理,具体可以参考下面的代码。

我的项目是基于Vue CLI构建的。

相关代码

// fit-table-columns.js
import "../assets/style/fit-table-columns.css"

/**
 * 自定义命令-关于el-table列固定(函数指令`v-fit-columns`)
 * @param app
 */
export default (app) => {
    app.directive('fit-columns', {
        // 指令具有一组生命周期钩子:
        // 在绑定元素的 attribute 或事件监听器被应用之前调用
        created() {
        },
        // 在绑定元素的父组件挂载之前调用
        beforeMount() {
        },
        // 在绑定元素的父组件挂载之后调用
        mounted(el, binding) {
            setTimeout(() => {
                adjustColumnWidth(el, binding.value);
            }, 300);
        },
        // 在包含组件的 VNode 更新之前调用
        beforeUpdate() {
        },
        // 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
        updated(el, binding) {
            el.classList.add("r-table");
            setTimeout(() => {
                adjustColumnWidth(el, binding.value);
            }, 300);
        },
        // 在绑定元素的父组件卸载之前调用
        beforeUnmount() {
        },
        // 在绑定元素的父组件卸载之后调用
        unmounted() {
        }
    })
}

/**
 * 调整列宽
 * @param table 使用调整列宽命令的table
 * @param padding 0
 */
function adjustColumnWidth(table, padding = 0) {
    // 获取table的colgroup节点DOM
    const colgroup = table.querySelector("colgroup");
    // 获取colgroup节点所有的列DOM
    const colDefs = [...colgroup.querySelectorAll("col")];
    colDefs.forEach((col) => {
        const clsName = col.getAttribute("name");
        // cells[0]为td的className=`${clsName}`的所有DOM
        // cells[1]为th的className=`${clsName}`的所有DOM
        const cells = [
            ...table.querySelectorAll(`td.${clsName}`),
            ...table.querySelectorAll(`th.${clsName}`),
        ];
        // 判断class="leave-alone"是否存在,存在则不需要设置此功能
        if (cells[0]?.classList?.contains?.("leave-alone")) {
            return;
        }
        // 通过css选择器获取class="cell"的DOM的宽度
        const widthList = cells.map((el) => {
            return el.querySelector(".cell")?.scrollWidth || 0;
        });
        // 获取一个最大的宽度
        const max = Math.max(...widthList);
        table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
            const oldWidth = el.offsetWidth;
            // 如果宽度没变就不添加padding
            if (max > oldWidth) {
                el.setAttribute("width", max + padding);
            }
        });
    });
}
// fit-table-columns.css
/** 表格显示内容的div样式 */
.el-table.r-table .cell {
    display: inline-block;
    white-space: nowrap;
    width: auto;
    overflow: auto;
}
/** 表头外的显示数据的div样式 */
.el-table.r-table .el-table__body-wrapper {
    overflow-x: auto;
}
// main.js
import {createApp} from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import router from './router'
import fitTableColumns from './plugins/fit-table-columns'
import App from './App.vue'

const app = createApp(App).use(router)
app.use(VueAxios, axios)
// 注册自定义命令`v-fit-columns`
fitTableColumns(app)
app.mount('#app')
// tableList.vue
<template>
	<el-table :data="elTable.tableData"
                stripe
                border
                height="250"
                v-fit-columns
                >
        <el-table-column type="selection" width="55" />
        <el-table-column type="index" label="序号" width="55"/>
        <el-table-column v-for="(item,index) in elTable.tableLabels" :key="index"
                         :property="item.property"
                         :label="item.label"
                         :width="item.width"
        >
        </el-table-column>
      </el-table>
</template>
<script>
export default {
  name: "tableList",
  data() {
    return {
      elTable: {
        tableLabels: [
          {label: '表名称', property: 'tableName'},
          {label: '表描述', property: 'tableComment'},
          {label: '创建时间', property: 'createTimeFormat'},
          {label: '更新时间', property: 'updateTimeFormat'}
        ],
        tableData: [{
			"createTimeFormat": "2022-04-07 15:27:06",
			"updateTimeFormat": null,
			"tableName": "oauth2_authorization_consent",
			"tableComment": ""
		},
		{
			"createTimeFormat": "2022-04-07 15:27:31",
			"updateTimeFormat": "2022-05-25 09:34:08",
			"tableName": "oauth2_registered_client",
			"tableComment": ""
		}]
      }
    }
  }
}
</script>

换行前table样式

表名称是换行的
在这里插入图片描述

处理后table样式

确实不换行了,列变宽了可以展示全部的数据了,但感觉还是不是很好,因为如果数据很多岂不是行变得很长。还有就是首次加载时,updated方法会执行多次导致table频繁闪动。
在这里插入图片描述

官方处理方式(推荐)

有这么个属性:show-overflow-tooltip,文档说明: 若需要单行显示可以使用 show-overflow-tooltip 属性,它接受一个 Boolean, 为 true 时多余的内容会在 hover 时以 tooltip 的形式显示出来。

修改代码

<template>
	<el-table :data="elTable.tableData"
                stripe
                border
                height="250"
                >
        <el-table-column type="selection" width="55" />
        <el-table-column type="index" label="序号" width="55"/>
        <el-table-column v-for="(item,index) in elTable.tableLabels" :key="index"
                         :property="item.property"
                         :label="item.label"
                         :width="item.width"
                         show-overflow-tooltip
        >
        </el-table-column>
      </el-table>
</template>

页面效果

加了show-overflow-tooltip我们再来看一看效果,列没有加宽,而是把溢出的数据用省略号替换并用Tooltip 组件的文字提示。
感觉不错,反正达到我想要的效果。
在这里插入图片描述

总结

一定要用认真看官方的文档,以免走弯路。但我这次还好起码学到了vue3关于自定义命令的相关知识。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Element Plus是一套基于Vue.js 2.0的桌面端组件库,其中的table表格组件支持合并单元格。在Element Plus中,我们可以通过设置span-method属性来自定义合并单元格的方法。具体来说,我们需要在data中定义一个方法,该方法接收两个参数:row和column,分别表示当前单元格所在的行和列。在该方法中,我们可以根据需要返回一个对象,该对象包含两个属性:rowspan和colspan,分别表示需要合并的行数和列数。例如,如果我们需要将第一列中相同的单元格合并,可以编写如下的span-method方法: ``` spanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex === 0) { let rowspan = 1; for (let i = rowIndex + 1; i < this.tableData.length; i++) { if (this.tableData[i][columnIndex] === this.tableData[rowIndex][columnIndex]) { rowspan++; } else { break; } } return { rowspan, colspan: 1 }; } } ``` 在上述代码中,我们首先判断当前单元格是否为第一列,如果是,则遍历该列下面的所有单元格,找到相同的单元格并计算需要合并的行数,最后返回一个包含rowspan和colspan属性的对象即可。 除了自定义span-method方法外,我们还可以通过设置column的属性来实现合并单元格。具体来说,我们可以在column中设置prop属性来指定需要合并的列,然后在需要合并的单元格中设置rowspan和colspan属性即可。例如,如果我们需要将第一列中相同的单元格合并,可以编写如下的column配置: ``` columns: [ { label: '入库编号', prop: 'batchNo', rowspan: ({ row, column, rowIndex, columnIndex }) => { if (columnIndex === 0) { let rowspan = 1; for (let i = rowIndex + 1; i < this.tableData.length; i++) { if (this.tableData[i][columnIndex] === this.tableData[rowIndex][columnIndex]) { rowspan++; } else { break; } } return rowspan; } } }, { label: '供应商', prop: 'supplierName', rowspan: ({ row, column, rowIndex, columnIndex }) => { if (columnIndex === 1) { let rowspan = 1; for (let i = rowIndex + 1; i < this.tableData.length; i++) { if (this.tableData[i][columnIndex] === this.tableData[rowIndex][columnIndex]) { rowspan++; } else { break; } } return rowspan; } } }, // 其他列的配置 ] ``` 在上述代码中,我们在column中设置了prop属性来指定需要合并的列,然后在需要合并的单元格中设置了rowspan属性来指定需要合并的行数。需要注意的是,rowspan属性可以是一个函数,该函数接收一个参数,该参数包含row、column、rowIndex和columnIndex四个属性,分别表示当前单元格所在的行、列以及行索引和列索引。在该函数中,我们可以根据需要返回需要合并的行数即可。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值