借助vue3-print-nb实现一个自动分页打印

2,175 阅读2分钟

背景

我有一个朋友,接到一个打印需求。现在有n多首古诗词,每首古诗词由(诗名,作者,内容组成),每首古诗词有长有短,内容多少不确定;需要有个打印功能,使用A4纸按顺序打印出全部的古诗词,每张A4纸可以有多首古诗词,每首古诗词(诗名、作者、内容)必须打印在一张A4纸上,不能被分开打印。

技术选型

考虑使用原生window.print实现,想了下,需要考虑各种场景,然后再封装,然后再使用,算了算了,还是使用打印插件吧,就vue3-print-nb了

搭建

新建vue3+vite项目

npm init vue@latest

引入vue3-print-nb

安装

npm i vue3-print-nb

配置

main.ts配置

import print from 'vue3-print-nb'
app.use(print)

打印

mock数据

新建poetries.ts文件,准备好古诗词

image.png

渲染数据,添加打印按钮

image.png

查看打印效果

image.png 一首词被分到两页去了,不满足需求

自动分页

  • 通过设置style="page-break-after:always"可以实现打印分页
  • 现在就是需要按class="poetry"的div进行分割,考虑到每张A4纸高度固定,所以通过判断每个poetry div的高度累加,当加上某个div的高度后,大于纸张高度时,就给上一个div加上style="page-break-after:always"

实现

const PAGE_HEIGHT = 1124 // A4纸高度

/**
 * 打印前,在需要分割的poetry div上添加page-break-after:always
 */
const printPre = () => {
  const splitDoms = document.getElementsByClassName('poetry')
  let startY = 0 // 占用A4纸的高度,从每页第一个poetry div的top值开始累加
  for (let i = 0; i < splitDoms.length; i++) {
    const splitDom = splitDoms[i]
    const splitValue = splitDom.getBoundingClientRect()
    if (startY === 0) {
      startY = splitValue.top
    }
    const pageHeight = splitValue.bottom - startY
    // 当加上当前div的高度大于A4纸高度时,给前一个div加上分页标识
    if (pageHeight > PAGE_HEIGHT) {
      startY = 0
      splitDoms[i - 1].style.pageBreakAfter = 'always' 
    }
  }
}

验证

<el-button type="primary" @click="printPre" v-print="print">打印</el-button>

image.png

ok,可以简单的交差了