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就不行,临界值是多少? 我也不知道
相关推荐
excel9 分钟前
webpack 核心编译器 十四 节
前端
excel16 分钟前
webpack 核心编译器 十三 节
前端
腾讯TNTWeb前端团队7 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰11 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪11 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪11 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy12 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom12 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom12 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github