从vue-print-nb到原生window.print:一次前端打印功能的技术选型踩坑实录
2026/4/17 17:06:50 网站建设 项目流程

从vue-print-nb到原生window.print:前端打印功能的技术选型实战

最近在开发一个发票打印功能时,我深刻体会到了前端打印功能的复杂性。作为一个Vue项目,最初我理所当然地考虑使用现成的打印插件,但实际开发过程中却遇到了各种预料之外的问题。本文将分享我从使用vue-print-nb插件到最终回归原生window.print的完整技术选型过程,希望能为遇到类似需求的开发者提供参考。

1. 为什么前端打印功能如此棘手

前端打印看似简单,实则暗藏玄机。浏览器提供的打印API虽然基础功能完善,但在实际业务场景中往往需要更精细的控制。特别是在Vue这类现代前端框架中,打印功能的实现需要考虑更多因素:

  • 样式控制难题:打印时的样式与屏幕显示样式存在差异,需要专门为打印设计CSS
  • 分页处理复杂:长表格或列表的自动分页经常出现问题
  • 动态内容处理:Vue组件渲染的动态内容在打印时可能无法正确保留
  • 浏览器兼容性:不同浏览器对打印功能的支持程度不一

提示:在开始实现打印功能前,务必先明确业务需求。是否需要支持多页打印?是否需要保留特定样式?这些因素将直接影响技术选型。

2. 主流Vue打印插件对比与尝试

2.1 vue-print-nb初体验

作为Vue生态中较为知名的打印插件,vue-print-nb是我的首选。安装和使用都非常简单:

npm install vue-print-nb --save

在main.js中引入并注册:

import Print from 'vue-print-nb' Vue.use(Print)

使用方式也很直观:

<div id="printArea"> <p>这是要打印的内容</p> </div> <button v-print="'#printArea'">打印</button>

优点

  • 集成简单,与Vue无缝衔接
  • 支持通过指令方式调用
  • 可以处理基本的打印需求

缺点

  • 对复杂表格支持不足
  • 大文档打印时容易出现内容截断
  • 项目活跃度较低,问题修复不及时

2.2 print-js的轻量级方案

当vue-print-nb无法满足需求时,我转向了print-js。这是一个更为轻量级的打印解决方案:

printJS({ printable: 'printContent', type: 'html', scanStyles: false, style: '@page { size: A4; margin: 0 }' })

对比分析

特性vue-print-nbprint-js
体积较大较小
活跃度
表格支持一般较好
样式控制有限更灵活

尽管print-js在表格支持上表现更好,但在处理超长表格时仍然存在问题,特别是当数据动态加载时。

3. 复杂表格打印的终极挑战

项目中的发票打印功能需要处理大量数据,这暴露了所有插件方案的局限性。主要问题包括:

  1. 内容截断:超过一页的内容无法自动分页
  2. 样式丢失:表格边框、背景色等打印时消失
  3. 性能问题:大数据量时打印预览加载缓慢

尝试过的解决方案:

  • 调整打印缩放比例(效果不佳,文字过小)
  • 手动分页(维护成本高,不灵活)
  • 使用CSS打印媒体查询(部分有效,但不解决根本问题)

最终发现,这些插件本质上都是对原生window.print的封装,当遇到复杂场景时,回归原生可能是更好的选择。

4. 回归原生:window.print的精细控制

放弃插件后,我深入研究了原生window.print API,结合CSS打印样式,终于找到了可靠的解决方案。

4.1 基础打印实现

最简单的打印调用:

window.print()

但实际项目中需要更精细的控制:

function customPrint() { const originalContents = document.body.innerHTML const printElement = document.getElementById('printArea') document.body.innerHTML = printElement.innerHTML window.print() document.body.innerHTML = originalContents }

4.2 关键CSS打印样式

实现完美打印的关键在于正确的CSS设置:

@media print { body * { visibility: hidden; } #printArea, #printArea * { visibility: visible; } #printArea { position: absolute; left: 0; top: 0; width: 100%; } .no-print { display: none !important; } table { page-break-inside: auto; } tr { page-break-inside: avoid; page-break-after: auto; } }

4.3 分页控制技巧

对于长表格,确保正确分页的几个要点:

  1. 使用page-break-inside: avoid防止行内分页
  2. 为表格设置width: 100%确保适应打印页面
  3. 通过@page规则设置页边距:
@page { size: A4; margin: 10mm; }

5. 实战:发票打印完整解决方案

结合上述经验,最终实现的发票打印方案包含以下关键部分:

5.1 HTML结构

<div id="invoice-container"> <!-- 打印区域 --> <div id="printArea"> <table class="invoice-table"> <!-- 发票表格内容 --> </table> </div> <!-- 操作按钮 --> <button @click="printInvoice" class="no-print">打印发票</button> </div>

5.2 JavaScript实现

methods: { printInvoice() { const printWindow = window.open('', '_blank') const printContents = document.getElementById('printArea').innerHTML const originalContents = document.body.innerHTML printWindow.document.write(` <!DOCTYPE html> <html> <head> <title>发票打印</title> <style> ${this.getPrintStyles()} </style> </head> <body> ${printContents} <script> window.onload = function() { setTimeout(function() { window.print() window.close() }, 100) } <\/script> </body> </html> `) printWindow.document.close() }, getPrintStyles() { return ` @page { size: A4; margin: 10mm; } body { font-family: Arial, sans-serif; } .invoice-table { width: 100%; border-collapse: collapse; page-break-inside: auto; } /* 更多打印样式... */ ` } }

5.3 注意事项

  1. 字体问题:打印时使用通用字体,确保跨平台一致性
  2. 图片处理:使用绝对路径或base64编码的图片
  3. 浏览器差异:测试不同浏览器的打印效果
  4. 性能优化:大数据量时考虑分批次打印

6. 技术选型决策树

根据项目需求选择打印方案:

  1. 简单内容打印

    • 推荐:vue-print-nb或print-js
    • 原因:快速实现,维护简单
  2. 复杂表格打印

    • 推荐:原生window.print + 自定义CSS
    • 原因:完全控制打印效果
  3. 跨浏览器兼容

    • 推荐:原生方案 + 功能检测
    • 原因:避免插件带来的不确定因素
  4. 动态内容打印

    • 推荐:先渲染再打印
    • 原因:确保所有数据正确显示

在项目后期,我们还实现了打印模板的可配置化,通过JSON定义发票格式,进一步提高了方案的灵活性。这个过程中最大的收获是:有时候看似"落后"的原生方案,反而能提供最稳定可靠的效果。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询