vue-print-nb打印el-table的各种坑(表头错位、更改边框样式、多一页空白页、表格打印不全)

1,710 阅读5分钟

1.表格打印不全

1.1.table宽度问题

因为el-table是js计算了合适的宽度然后动态设置table的width的:

image.png

但是打印的时候就这个固定的witdh就不适用于页面的宽度了,所以可以把table宽度设置为100%,同时把table-layout设置为auto。注意如果使用了scoped,scss需要加::v-deep进行样式穿透,此外element ui是设置的行内样式width,所以了我在这里干脆设置了优先级为!important。(参考:vue 中 vue-print-nb 表格打印不全的问题_vue-print-nb打印form不全_小手挥挥的博客-CSDN博客

::v-deep table {
    table-layout: auto;
}
::v-deep .el-table__header-wrapper .el-table__header {
    width: 100% !important;
}
::v-deep .el-table__body-wrapper .el-table__body {
    width: 100% !important;
}

1.2.show-overflow-tooltip问题

此外如果el-table设置了show-overflow-tooltip为true的话,即使设置了以上的的样式,还是会有打印不全的问题,而且会出现表头可以打印完全,但表体宽度超过页面宽度的情况。所以如果设置了show-overflow-tooltip为true,则还需设置以下样式:

::v-deep .el-table .cell.el-tooltip {
    text-overflow: clip;
    white-space: normal;
    min-width: none;
    width: auto !important;
    border: none !important;
}

2.表头错位

el-table是用两个table标签来组装成一个表格的,表头是一个table,表体是一个table。

image.png

因为我们在第一步设置了table-layout为auto,所以两个表格的边框会有错位的现象。(我用的别人的图,来源:element - 如何解决使用vue-print-nb打印el-table出现表头和数据列边框错位? - SegmentFault 思否

image.png

发现了一个现象,当原本页面上的el-table宽度超过页面宽度、x方向有滚动条时,直接打印就不会有表头错位问题,看了一下el-table表体table的overflow设置的时auto,但我试了一下设置为visible或hidden,el-table宽度没超过页面时直接打印,表头还是会错位,所以不知道这里的原因。

我的解决方法是把表头数据插入到表体数据的最开始,让表头数据在表体table的第一行,然后把el-table的原本的表头隐藏起来,这样表头数据显示在原本的表体第一行,也就相当于有表头了。表头和表体都在一个table标签里,就不会出现表头错位问题了。

比如表头是【 姓名 | 年龄 | 住址 | 性别 】,原本的表格数据如下:

tableData: [
    {
        name: "张三",
        age: 50,
        address: "中国",
        gender: "01"
    },
    {
        name: "李四",
        age: 66,
        address: "外国",
        gender: "02"
    },
    ...
]

那么可以把数据改造成这样:

tableData: [
    // 数组的第一个元素就是表头的信息
    {
        name: "姓名",
        age: "年龄",
        address: "住址",
        gender: "性别"
    },
    // 下面才是原本的表体的数据
    {
        name: "张三",
        age: 50,
        address: "中国",
        gender: "01"
    },
    {
        name: "李四",
        age: 66,
        address: "外国",
        gender: "02"
    },
    ...
]

再把el-table的show-header属性设置为false,这样就不会有表头错位问题了。

下面是我写的一个专门用于打印的表格组件的部分代码(纯手打,有错,不要直接复制粘贴):

<template>
    <el-table 
        :id="id
        :data="tableData"
        border
        :show-header="false" // 隐藏表头
        :row-class-name="handleRowClass" // 设置第一行的样式,使其看起来像表头
     >
        <el-table-column
            v-for="col in column"
            :key="col.prop || col.label
            :label="col.label || ''"
            :prop="col.prop"
        >
        ... // 这里可以不写,也可以根据实际情况按字典翻译啥的
        </el-table-column>
    </el-table>
</template>

<script>
export default {
    name: "PrintTable",
    props: {
        // 用vue-print-nb组件唤起打印需要指定打印元素的id
        id: {
            type: String,
            default: null
        },
        // 表格数据(不含表头)
        data: {
            type: Array,
            default: () => []
        },
        // 表格列信息,数据结构是[{prop: "xx", label: "yy"},{...},...]
        columns: {
            type: Array,
            default: () => []
        },
    },
    data() {
        return {
            // 含表头数据的表格数据
            tableData: []
        }
    },
    watch: {
        // 监听表格数据,在其开始插入表头行数据
        data: {
            handler(newVal, oldVal) {
                const header = {};
                this.columns.forEach(col => {
                    header[col.prop] = col.label;
                });
                this.tableData = [header, ...this.data];
            },
            deep: true,
            immediate: true
        }
    },
    methods: {
        // 设置第一行的类名
        handleRowClass({row, rowIndex}) {
            if(rowIndex === ) return "print-table-header";
            else return "";
        }
    }
}
</script>

3.修改边框样式

我们的要求是显示所有边框,并且都为1px宽的黑色。然后遇到了原始边框样式在干扰的问题,仔细查看发现el-table的边框有些是用after、before做的,所以需要清除掉。

有两种方式:

  1. 设置el-table的border为true,且利用cell-styleheader-cell-style属性改变边框颜色,然后在最外层加边框,具体可参考elementui 更改 el-table 表头样式及修改el-table表格边框的注意事项_el-table边框-CSDN博客,这种方式打印预览的表格外层边框会和单元格边框对不拢,第二种方法更好一些。

  2. 直接粗暴地更改样式,并设置优先级最高

// 设置表格边框样式
::v-deep table {
    table-layout: auto;
    border: 1px solid black !important;
    border-color: black !important;
    border-collapse: collapse;
    font-size: 8px !important;
    color: black !important;
    td {
        border: 1px solid  black !important;
    }
    th {
        border: 1px solid black !important;
        border-bottom: none !important;
        width: auto !important;
     }
}
// 清楚原来的边框样式
::v-deep .el-table--border::after,
.el-table--group::after
.el-table::before {
    background-color: transparent;
}
::v-deep .el-table::before {
    height: 0px;
}
::v-deep .el-table--border::after {
    width: 0px;
}
::v-deep el-table--border {
    border: none;
}
::v-deep .el-table--group::after, 
el-table--border::after {
    width: 0;
}
::v-deep .el-table--group, 
el-table--border border {
    border: none !important;
}

(参考el-table去掉最外层的边框线 - pz_ww - 博客园 (cnblogs.com)

4.去掉空白页

主要是设置html的样式:

html {
    margin: 0px;
    height: auto;
}
body {
    border: solid 1px white;
    margin: 10mm 15mm 10mm 15mm;
}

参考自解决vue-print-nb打印时多出一页空白,vue-print-nb打印有空白页-CSDN博客

注意以上所有的样式都需要在@media print{}里写哈

ok,以上就是我用vue-print-nb打印el-table的各种坑,有些不对的地方还请说出来一起交流