ReactJS中JSX实现无弹窗直接打印页面/PDF的方案
ReactJS 实现无弹窗直接打印票据(公交/电影票)
核心说明
浏览器原生的window.print()默认会弹出打印设置窗口,这是浏览器的安全限制,网页端无法直接绕过。要实现无弹窗静默打印,需要用户提前在浏览器设置中允许当前站点的静默打印权限,或者使用Electron等桌面应用框架调用系统打印API。
下面给出基于React JSX的票据打印完整实现,包含指定区域打印、自定义打印样式,以及模拟静默打印的可行方案。
完整代码示例
import React, { useRef } from "react"; import styles from "../Components/ReactPdfPrint.module.css"; import "bootstrap/dist/css/bootstrap.min.css"; const handlePrint = (printRef) => { if (!printRef) return; // 创建打印窗口 const printWindow = window.open("", "_blank"); // 复制目标区域的HTML和页面样式 const printContent = printRef.innerHTML; const styleSheets = Array.from(document.styleSheets) .map(sheet => { try { return sheet.cssText || Array.from(sheet.cssRules).map(rule => rule.cssText).join(''); } catch (e) { // 跨域样式无法访问,直接跳过 return ''; } }) .join(''); // 写入打印窗口内容 printWindow.document.write(` <html> <head> <title>票据打印</title> <style> ${styleSheets} /* 适配打印的样式 */ body { margin: 0; padding: 10px; } @media print { @page { size: auto; margin: 0; } body { margin: 0; } } </style> </head> <body>${printContent}</body> </html> `); printWindow.document.close(); // 等待内容加载完成后触发打印 printWindow.onload = () => { // 尝试静默打印(需浏览器提前授权) printWindow.print(); // 打印完成后自动关闭窗口 setTimeout(() => printWindow.close(), 100); }; }; const ReactPdfPrint = () => { const ticketRef = useRef(null); return ( <> {/* 票据区域,用ref标记为打印目标 */} <div ref={ticketRef} className={styles.ticket}> <img src="./ticketLogo.jpg" alt="公交票务" height="30px" width="30px" /> <p className={styles.centered}> 公交乘车凭证 <br /> 起点:XX地铁站 <br /> 终点:XX商圈站 </p> <table> <thead> <tr> <th className={styles.quantity}>票种</th> <th className={styles.description}>详细信息</th> <th className={styles.price}>金额</th> </tr> </thead> <tbody> <tr> <td className={styles.quantity}>1</td> <td className={styles.description}>成人单程票</td> <td className={styles.price}>¥2.00</td> </tr> <tr> <td className={styles.quantity} /> <td className={styles.description}>总金额</td> <td className={styles.price}>¥2.00</td> </tr> </tbody> </table> <p className={styles.centered}> 乘车时间:2024-05-20 08:30 <br /> 票号:BUS-20240520-00123 </p> </div> <p className="centered"> 感谢使用公共交通! </p> {/* 打印触发按钮 */} <button id="btnPrint" className={styles.container} onClick={() => handlePrint(ticketRef.current)} > 打印票据 </button> </> ); }; export default ReactPdfPrint;
关键细节说明
- 指定打印区域:通过
useRef获取票据DOM元素,仅打印目标区域内容,避免打印整个页面的无关元素。 - 自定义打印样式:在打印窗口中注入原页面样式,并添加
@media print媒体查询,确保票据排版适配打印纸尺寸。 - 静默打印的实现限制:
- 网页端必须用户手动在浏览器设置中开启「允许此站点静默打印」权限,否则仍会弹出打印设置窗口。
- 桌面应用场景(如Electron)可替换为以下代码实现真正无弹窗打印:
// Electron渲染进程代码 const { ipcRenderer } = require('electron'); ipcRenderer.send('print-silent', printContent); // Electron主进程代码 const { ipcMain } = require('electron'); ipcMain.on('print-silent', (event) => { mainWindow.webContents.print({ silent: true, printBackground: true }); });
配套样式文件参考(ReactPdfPrint.module.css)
.ticket { width: 300px; border: 1px solid #000; padding: 15px; margin: 20px auto; font-family: Arial, sans-serif; } .centered { text-align: center; margin: 10px 0; } table { width: 100%; border-collapse: collapse; margin: 15px 0; } th, td { border: 1px solid #000; padding: 5px; text-align: center; } .description { text-align: left; } .container { display: block; margin: 0 auto; padding: 8px 16px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } .container:hover { background-color: #0056b3; }
内容的提问来源于stack exchange,提问作者Manthan Vaja
相关产品推荐
相关产品推荐

