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就不行,临界值是多少? 我也不知道
相关推荐
etsuyou几秒前
Koa学习
服务器·前端·学习
Easonmax16 分钟前
【CSS3】css开篇基础(1)
前端·css
大鱼前端34 分钟前
未来前端发展方向:深度探索与技术前瞻
前端
昨天;明天。今天。39 分钟前
案例-博客页面简单实现
前端·javascript·css
天上掉下来个程小白41 分钟前
请求响应-08.响应-案例
java·服务器·前端·springboot
萧鼎1 小时前
JavaScript可视化
javascript
周太密1 小时前
使用 Vue 3 和 Element Plus 构建动态酒店日历组件
前端
安冬的码畜日常1 小时前
【玩转 JS 函数式编程_008】3.1.2 JavaScript 函数式编程筑基之:箭头函数——一种更流行的写法
开发语言·javascript·ecmascript·es6·this·箭头函数
时清云2 小时前
【算法】合并两个有序链表
前端·算法·面试
小爱丨同学2 小时前
宏队列和微队列
前端·javascript