Electron与Vue集成实现小票静默打印完整方案

作者:山岚时间:2026-10-22 19:19:35浏览:275

本文详解在Electron结合Vue的项目中如何实现小票打印功能。通过对比两种打印方案,重点介绍利用webview元素进行静默打印的方法。内容涵盖主线程获取打印机列表、渲染线程通过IPC通信交互、在HTML中排版打印内容,以及最终调用webview.print()完成打印的全过程,附带关键代码示例。

需求背景与方案分析

一、需求背景

公司项目要求利用Electron调用系统打印机,完成小票打印任务。

二、方案分析

Electron环境下实现打印主要有两种途径:

第一种方式是利用Window的webContents对象。此方法需要单独开辟一个打印窗口,虽然可以将其隐藏,但窗口间的通信调用相对复杂。

第二种方式是使用页面中的webview元素来调用打印功能。这种方式可以将webview嵌入在当前页面中并隐藏,其通信机制更为简单直接。

这两种对象在调用打印方法时的使用逻辑基本一致。

本文采用第二种方法来实现静默打印功能。

获取打印机列表与主从线程通信

三、具体实现步骤

1、获取可用打印机列表:首先需要了解当前设备上有哪些可用的打印机。具体做法是在渲染线程中,通过Electron的ipcRenderer对象发送事件至主线程以获取列表。(注:本文中的渲染线程对应print.vue文件)。

(1)主线程(electron.js)相关代码示例如下:


//引入electron
import electron from 'electron';

//创建一个浏览器对象
const window = new electron.BrowserWindow({
  width,
  height,
  frame: false,
  show: false,
  backgroundColor: '#4b5b79',
  minWidth: 1024,
  minHeight: 768,
  webPreferences: { webSecurity: false },
 });
 
//在主线程下,通过ipcMain对象监听渲染线程传过来的getPrinterList事件
electron.ipcMain.on('getPrinterList', (event) => {
  //主线程获取打印机列表
  const list = window.webContents.getPrinters();
  
  //通过webContents发送事件到渲染线程,同时将打印机列表也传过去
  window.webContents.send('getPrinterList', list);
});

===============================================================================

(2)渲染线程(print.vue文件)相关代码示例如下:


<template>
</template>
<script>
  //引入ipcRenderer对象,该对象和主线程的ipcMain通讯
  import { ipcRenderer } from 'electron';
  
  //渲染线程主动发送getPrinterList事件到主线程请求打印机列表
  ipcRenderer.send('getPrinterList'); 
  
  //监听主线程获取到打印机列表后的回调
   ipcRenderer.once('getPrinterList', (event, data) => {
    //data就是打印机列表
    this.printList = data;
   });
</script>

//获取打印机列表完成

小票排版与静默打印实现

2、(核心环节)在获取打印机列表后,需借助Electron自带的标签来实现小票的排版效果。这里的标签指的是用于显示打印内容的容器。

(1)使用前,需新建一个print.html文件,将需要打印的内容通过该文件展示。本项目的需求是将打印内容通过Canvas绘制后,转换为Base64格式的图片资源,再放入该文件中显示,相关代码如下:


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <style>
 //@page样式是用来设置打印机打印出来的样式,例如设置小票外边距样式
  @page {
   margin: 0px;
  }
 </style>
</head>
<body id='bd'>
</body>
<script>
  //引入ipcRenderer对象
 const {ipcRenderer} = require('electron')
 
 //监听渲染线程传过来的webview-print-render事件
 ipcRenderer.on('webview-print-render', (event, deviceInfo) => {
  // 动态创建一个img标签,然后插入到<body>中。deviceInfo是渲染线程传过来的数据
  let html = '';
  html = `<img src="${deviceInfo.imgSource}"
   width="${deviceInfo.imgWidth}px"
   height="${deviceInfo.imgHeight}px">`;
  document.getElementById('bd').innerHTML = html;
  
  //当图片插入到页面后,通过ipcRenderer对象的sendToHost方法和渲染线程通讯,告诉渲染线程打印的内容已经准备完毕,请开始打印操作
  ipcRenderer.sendToHost('webview-print-do');
 });
</script>
</html>

(2)HTML文件创建完毕后,需将其引入到print.vue文件中。该标签需在print.vue中显式定义,但必须使用v-show="false"进行隐藏,严禁使用v-if。这是因为我们需要打印的DOM节点必须存在于页面上,仅是不进行视觉展示而已。


<script>
mounted() {
  //当vue节点渲染完成后,获取<webview>节点
  const webview = this.$refs.printWebview;
  
  //监听<webview>里面的消息,也就是监听print.html里面的ipcRenderer.sendToHost发送的事件,当该事件发送成功后就会进入下面的回调事件中执行打印操作。
  webview.addEventListener('ipc-message', (event) => {
   if (event.channel === 'webview-print-do') {
    //如果收到<webview>传过来的事件,名为"webview-print-do",就执行 webview.print打印方法,打印<webview>里面的内容。
    webview.print(
     {
      //是否是静默打印
      silent: true,
      printBackground: true,
      //打印机的名称,就是本文一开始获得的打印机列表其中一个
      deviceName: 'xxx',
     },
     (data) => {
      //这个回调是打印后的回调事件,data为true就是打印成功,为false就打印失败
      console.log('webview success', data);
     },
    );
   }
  });
},
</script>

至此,Electron调用打印机打印小票的功能即告完成。

总结

以上介绍了在Electron与Vue项目中实现打印小票功能的具体代码及步骤,希望能对读者有所帮助。如有任何疑问,欢迎留言,作者会及时回复。

作者最新文章