在Vue3项目里做打印功能时,Print.js是一个轻量且常用的前端打印库。它通过隐藏iframe来加载待打印内容,并调用浏览器原生打印对话框,不需要额外安装浏览器插件。与Node.js配合时,通常由Node.js负责生成或整理需要打印的HTML片段、PDF文件地址或图片资源,前端拿到数据后用Print.js触发打印。下面先梳理在Vue3中的集成步骤。

Print.js的安装非常简单,只需要在项目根目录执行npm安装命令即可。它不依赖jQuery,打包体积较小,适合现代前端工程使用。引入后可以直接在组件的响应式方法里调用,打印内容既可以是页面中已经存在的DOM节点,也可以是一段动态拼接的HTML字符串,还可以是远程的PDF文件或图片地址。下面先看安装和基础调用的代码示例。
一、Vue3中Print.js的安装与基础用法
在Vue3项目里使用Print.js,第一步是通过npm或yarn把依赖装好。以npm为例,执行npm install print-js即可完成安装。由于Print.js本身已经提供了ES模块导出,因此可以直接在<script setup>语法中通过import引入,无需额外配置全局插件。安装完成后,建议在需要打印的组件中单独引入,避免增加全局打包体积。
引入之后,就可以调用printJS函数来触发打印。最简单的用法是直接传入一个DOM节点的id,并将type设置为html。Print.js会把这个节点复制到隐藏的iframe中,然后打开浏览器打印预览窗口。下面是一个典型的基础调用示例:
import printJS from 'print-js'
const handlePrint = () => {
printJS({
printable: 'print-area',
type: 'html',
css: ['/print.css'],
scanStyles: false,
targetStyles: ['*']
})
}
上面的代码中,printable是被打印区域的id,css用来加载额外的打印样式文件,scanStyles设置为false表示不扫描页面所有样式,而targetStyles则指定只复用某些样式。这样的组合可以在一定程度上避免样式污染,但需要根据实际页面结构调整。待打印区域在模板中通常长这样:
<div id="print-area">
<h2>订单明细</h2>
<table>
<tr><td>商品名称</td><td>单价</td></tr>
<tr><td>无线键盘</td><td>129</td></tr>
</table>
</div>
除了打印HTML区域,Print.js还支持直接打印远程PDF和图片。例如printJS({ printable: '/files/report.pdf', type: 'pdf' }),浏览器会打开PDF预览并唤起打印。对于图片类型,可以传入单个图片地址或图片数组,Print.js会依次渲染并调用打印。需要注意的是,远程资源必须允许当前域名访问,否则会遇到跨域限制。
二、Print.js与Node.js服务端协作的典型模式
Print.js本身运行在浏览器端,Node.js并不会直接参与打印动作,但服务端可以承担打印内容生成、数据拼装、鉴权校验和静态资源输出等工作。一种常见的架构是:前端请求Node.js提供的接口,接口根据业务参数查询数据库并返回一段HTML字符串,前端拿到这段字符串后交给Print.js进行打印。这样做的好处是可以把打印模板放在服务端管理,避免前端硬编码过多业务逻辑。
例如,使用Express框架可以这样写一个返回打印HTML的接口:
app.get('/api/print/order/:id', async (req, res) => {
const order = await getOrder(req.params.id)
const html = `<html><body><h1>订单 ${order.id}</h1><p>金额:${order.amount}</p></body></html>`
res.type('html').send(html)
})
前端在拿到该接口返回的HTML字符串后,可以这样调用Print.js:printJS({ printable: htmlString, type: 'html' })。此时Print.js会将字符串写入iframe并触发打印。需要注意的是,如果返回的HTML字符串里引用了外部CSS或图片,必须确保这些资源的URL是绝对路径或可访问的相对路径,否则打印结果会出现样式丢失或图片无法加载的情况。
另一种协作模式是Node.js直接生成PDF文件并返回文件地址,前端拿到地址后用Print.js打印PDF。这种方式适合对打印格式要求较高的场景,因为服务端可以使用Puppeteer等工具精确控制PDF排版。Print.js拿到PDF地址后只是简单打开并触发打印,实际的渲染工作由浏览器完成。这里要特别留意鉴权头的问题:如果PDF接口需要携带Cookie或Authorization头,Print.js默认的iframe加载方式可能无法自动带上这些凭证,需要改用带签名的临时URL或者在前端先下载PDF再打印。
三、Print.js优缺点分析与选购建议
Print.js最明显的优点是轻量、API简单、上手快。对于只需要打印页面某个区域或远程PDF的常规需求,Print.js可以很快实现,不需要引入额外的大型依赖。它还支持打印HTML、PDF、图片和JSON多种类型,在处理简单订单、报表、标签等场景时非常实用。同时Print.js不依赖jQuery,对Vue3等现代框架的兼容性较好。
但Print.js也存在一些明显短板。它的打印样式控制能力较弱,尤其是遇到复杂分页、页眉页脚、固定表头等需求时,往往需要配合大量CSS媒体查询才能勉强实现。由于Print.js使用隐藏iframe复制内容,页面原有的部分样式可能因为作用域隔离而失效,需要通过css参数手动引入。另一个问题是它不支持服务端静默打印,也就是无法绕过浏览器打印对话框直接输出到打印机,这在需要批量打印或自动化打印的业务中会受限。
如果和原生window.print()对比,Print.js的优势是能圈定打印区域,避免把整个页面一起打印出来。和html2canvas方案相比,Print.js打印的是真实文本和向量内容,清晰度更高,而html2canvas会把内容变成图片,打印放大后容易模糊。如果项目对打印质量要求较高,或者需要打印复杂表格和多页内容,建议优先考虑服务端生成PDF的方案,例如使用Puppeteer在Node.js中渲染并输出PDF,前端只负责下载或预览。选购时可以根据打印内容复杂度、是否需要静默打印、是否要求高保真样式三个维度来判断。
四、常见问题与注意事项汇总
在实际使用Print.js的过程中,有几个高频问题需要提前关注。首先是打印样式丢失问题,表现为打印预览中的元素没有背景色、字体大小异常或者间距错乱。原因通常是隐藏iframe无法继承原页面的完整样式,解决方法是把打印需要的样式单独写在一个CSS文件里,通过css参数加载,或者设置scanStyles: true扫描全部样式。对于背景色和图片背景,浏览器默认在打印时不会显示,需要在CSS里显式加上-webkit-print-color-adjust: exact和print-color-adjust: exact。
其次是分页异常,比如表格行被截断、内容跨页断开。Print.js本身不提供分页控制,需要在打印CSS中使用page-break-inside: avoid、page-break-before: always等规则来手动调整。对于长表格,建议给每一页重复表头的区域设置display: table-header-group,这样浏览器会尽量在换页时自动带上表头。
另外,打印区域里有图片时,如果图片资源加载过慢,可能导致打印预览时图片显示空白。可以在触发打印前确保所有图片已经加载完成,或者在Print.js回调前使用Promise.all预加载图片。重复打印同一个区域时,偶尔会出现DOM节点ID冲突或内容为空的情况,建议每次打印前重新获取最新的DOM引用,并避免在打印过程中修改原区域的内容。
最后还要注意Vue3的响应式更新时机。如果在修改了响应式数据后立即调用Print.js,可能会因为DOM尚未更新而打印出旧内容。建议在nextTick回调中触发打印,或者使用setTimeout等待一帧。对于Node.js返回的远程HTML,若其中包含用户输入,务必做好HTML转义,防止打印内容被注入恶意脚本。

