web打印踩坑记录

项目背景

vue2.0项目,使用vue-print-nb插件实现打印功能

以下内容跟框架和插件关系不大,主要跟打印功能相关

踩坑记录:

1. 每页都需要页头页尾,比如页头是基本信息,页尾里是签名和备注提示,所以需要每页都有

table中thead和tfoot里的内容在打印分页时会自动带入每一页中,所以使用table排版,把页头放进thead中,页尾放入tfoot中,即可实现每页带入。

但是!像我们的项目各个模块的打印排版已经用div写好了,现在要改造,为了节约成本,我们在增加了一个全局的layout组件👇

html 复制代码
<template>
  <table>
      <thead><tr><th>
          <div>
            <slot name="header" />
          </div>
      </th></tr></thead>
      <tbody><tr><td>
          <div>
            <slot name="body" />
          </div>
      </td></tr></tbody>
      <tfoot><tr><td>
          <div>
            <slot name="footer" />
          </div>
      </td></tr></tfoot>
  </table>
</template>

然后在需要改造的打印模块中将表头内容表尾区分一下放入对应的slot中👇

html 复制代码
<PrintLayout>
<template slot="header"></template>
<template slot="body"></template>
<template slot="footer"></template>
</PrintLayout>
2. 打印尺寸不统一,可能文件a固定要用A5,文件b有的部门用A4有的部门用A5

固定用某个尺寸可以直接设置@page{size: 'xxx'},所有打印统一的话直接全局设置最方便

css 复制代码
/* Keyword values for scalable size */ 
size: auto; 
size: portrait; 
size: landscape; 
/* <length> values */ 
/* 1 value: height = width */ 
size: 6in; 
/* 2 values: width then height */ 
size: 4in 6in; 
/* Keyword values for absolute size */ 
size: A4; 
size: B5; 
size: JIS-B4; 
size: letter; 
/* Mixing size and orientation */ 
size: A4 portrait;

我们项目是不统一的,所以如果是固定用某个小尺寸,会直接写死px值然后用margin: 0 auto;居中;不是固定尺寸的话需要自适应,字体样式排版需要多调试😮‍💨。

3. 页尾需要固定在每页的最下面 (这是最坑的地方😠)

最先尝试的是尺寸计算的方式,这时候需要固定一个尺寸,比如1920像素下A4高度一页大概是1082px、A5高度一页大概是793px;

  • 如果是用table写的,可以在dom渲染数据后获取每个tr的高度然后重组数据,即dataList刚开始是一个[],渲染出一个table,随后获取到所有的tr,循环去计算高度将dataList拆分成一个二维数据[[],[]], 然后每一项渲染出一个table,每个table加page-break-after:alawys;分页。这样的好处是算的比较精细,不容易出现高度误差的问题。示意图just like👇
  • 如果是像我们用的是layout,排版都是一团一团通过slot塞进table里的,一个打印里还有有两三个dataList,就不太适用上面的方式,所以使用的是整体计算思维,在tbody下面填充将最后一页的tfoot撑到最下面,填充的高度就是需要计算的高度:每页固定尺寸减去thead高tfoot高就是每页中间tbody的高度a,每页tbody的高度 - tbody的高度 % 每页tbody的高度。示意图just like👇

存在问题:

  1. 需要固定一个尺寸,这个尺寸本身就是不准确的,像素不同纸张尺寸转化成的px数值就不同;
  2. margin值会被遗漏问题,tfoot下级的元素有margin值,获取tfoot的高度会不包含这个margin值的,thead、tbody同理,这时候页面就出现了未被计算的额外高度,会出现多一页纸的情况;
  3. 需要加载图片,图片load是需要时间的,会存在计算高度的时候图片还没loaded,就被忽略了,图片就是额外多出来的高度了

最后采用的方法是footer部分fixed排版, 给tr元素fixed定位,tfoot给固定高度占位,这样页尾就会每页固定在最底部,又因为tfoot有高度占位了,不会和内容重叠显示;

css 复制代码
// html
 <tfoot>
  <tr class="foot-fixed">
    <td>
      <div class="footer-content">
        <slot name="footer" />
      </div>
    </td>
  </tr>
</tfoot>

// js

const tfoot = document.querySelector('tfoot') || {} // 页脚
const footerContent = document.querySelector('footer-content')
let footHeight = footerContent.clientHeight
if (!footHeight) {
    footHeight = 100
    // 给个高度占位 这样body的内容就不会到下面来跟fixed的脚重叠
}
tfoot.style.height = `${footHeight}px`


// css
table {
  min-height: 100vh;
}
.foot-fixed {
  position: fixed;
  bottom: 0;
  z-index: -1;
  width: 800px;
  max-width: 100%;
}

存在问题:

  1. 不能生成两份文件同时预览打印,这时候会有两个fixed的foot,每页底部会有同时显示重叠的两个foot
  2. 需要加载图片,图片load是需要时间的,js计算高度给tfoot的时候,图片还没加载出来,就会被漏掉了,图片再加载出来显示就会和已有内容重叠在一起,可以给个包含图片的最小高度给图片显示先留位置,也可以等图片onload了再去加载打印dom

注意点记录

  1. 父级有元素设置transform样式,表格内元素设置fixed会不生效
  2. 页头跟纸张长度的比例有个临界值,超过了就不会每页都渲染页头,比如页头高度400,在A4就会每页渲染,A5就不行,临界值是多少? 我也不知道
相关推荐
M_emory_10 分钟前
解决 git clone 出现:Failed to connect to 127.0.0.1 port 1080: Connection refused 错误
前端·vue.js·git
Ciito14 分钟前
vue项目使用eslint+prettier管理项目格式化
前端·javascript·vue.js
成都被卷死的程序员1 小时前
响应式网页设计--html
前端·html
fighting ~1 小时前
react17安装html-react-parser运行报错记录
javascript·react.js·html
老码沉思录1 小时前
React Native 全栈开发实战班 - 列表与滚动视图
javascript·react native·react.js
abments1 小时前
JavaScript逆向爬虫教程-------基础篇之常用的编码与加密介绍(python和js实现)
javascript·爬虫·python
mon_star°1 小时前
将答题成绩排行榜数据通过前端生成excel的方式实现导出下载功能
前端·excel
Zrf21913184551 小时前
前端笔试中oj算法题的解法模版
前端·readline·oj算法
老码沉思录1 小时前
React Native 全栈开发实战班 - 状态管理入门(Context API)
javascript·react native·react.js
文军的烹饪实验室2 小时前
ValueError: Circular reference detected
开发语言·前端·javascript