当前位置 博文首页 > xiaoyan2017:基于vue3.0+electron新开窗口|Electron多开窗体|父
最近一直在折腾Vue3+Electron技术结合的实践,今天就来分享一些vue3.x和electron实现开启多窗口功能。
开始本文之前,先来介绍下如何使用vue3和electron来快速搭建项目。
目前electron.js的star高达89.3K+,最新稳定版v11.2.3。
使用vue开发electron应用,网上有个比较火的脚手架electron-vue,不过里面的版本太低,而且使用的是vue2.x语法。
今天主要分享的是vue3语法开发electron应用,所以只能手动搭建开发环境。
npm install -g @vue/cli
具体的选项配置,大家根据需要勾选。
vue create vue3_electron
安装vue-cli-plugin-electron-builder插件。
cd vue3_electron vue add electron-builder
之后的安装过程中会提示安装electron版本,选择最新版安装就行。
npm run electron:serve npm run electron:build
非常简单,没有几步就能快速手动搭建vue3+electron项目,下面就能愉快的开发了。
一般项目中需要新建多开窗口的功能,使用Electron来创建也是非常简单的。一般的实现方法是 new BrowserWindow({...}) 窗口,传入参数配置即可快速新建一个窗口。
<body> <button id="aaa">打开A窗口</button> <button id="bbb">打开B窗口</button> <button id="ccc">打开C窗口</button> </body> <script> import path from 'path' import { remote } from 'electron' let BrowserWindow = remote.BrowserWindow; let winA = null; let winB = null; let winC = null; document.getElementById("aaa").onclick = function(){ winA = new BrowserWindow ({width: 1000, height:800}) winA.loadURL("https://aaa.com/"); winA.on("close", function(){ winA = null; }) } document.getElementById("bbb").onclick = function(){ winB = new BrowserWindow ({width: 900, height:650}) winB.loadURL("https://bbb.com/"); winB.on("close", function(){ winB = null; }) } document.getElementById("ccc").onclick = function(){ winC = new BrowserWindow ({width: 500, height:500}) winC.loadURL(`file://${__dirname}/news.html`); winC.on("close", function(){ winC = null; }) } </script>
具体的参数配置,大家可以去查阅文档,electron官网中都有非常详细的说明。
https://www.electronjs.org/docs/api/browser-window
但是这种方法每次都要新建一个BrowserWindow,有些挺麻烦的,能不能像下面代码片段这样,直接通过一个函数,然后传入配置参数生成新窗口,显然是可以的。
windowCreate({ title: '管理页面', route: '/manage?id=123', width: 750, height: 500, backgroundColor: '#f9f9f9', resizable: false, maximize: true, modal: true, })
background.js配置
'use strict' import { app, BrowserWindow } from 'electron' const isDevelopment = process.env.NODE_ENV !== 'production' import { Window } from './windows' async function createWindow() { let window = new Window() window.listen() window.createWindows({isMainWin: true}) window.createTray() } app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) app.on('ready', async () => { createWindow() }) if (isDevelopment) { if (process.platform === 'win32') { process.on('message', (data) => { if (data === 'graceful-exit') { app.quit() } }) } else { process.on('SIGTERM', () => { app.quit() }) } }
新建一个 window.js 来处理主进程所有的函数。
import { app, BrowserWindow, ipcMain, Menu, Tray } from "electron"; import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import path from 'path' export const windowsCfg = { id: '', //唯一id title: '', //窗口标题 width: '', //宽度 height: '', //高度 minWidth: '', //最小宽度 minHeight: '', //最小高度 route: '', // 页面路由URL '/manage?id=123' resizable: true, //是否支持调整窗口大小 maximize: false, //是否最大化 backgroundColor:'#eee', //窗口背景色 data: null, //数据 isMultiWindow: false, //是否支持多开窗口 (如果为false,当窗体存在,再次创建不会新建一个窗体 只focus显示即可,,如果为true,即使窗体存在,也可以新建一个) isMainWin: false, //是否主窗口(当为true时会替代当前主窗口) parentId: '', //父窗口id 创建父子窗口 -- 子窗口永远显示在父窗口顶部 【父窗口可以操作】 modal: false, //模态窗口 -- 模态窗口是禁用父窗口的子窗口,创建模态窗口必须设置 parent 和 modal 选项 【父窗口不能操作】 } /** * 窗口配置 */ export class Window { constructor() { this.main = null; //当前页 this.group = {}; //窗口组 this.tray = null; //托盘 } // 窗口配置 winOpts(wh=[]) { return { width: wh[0], height: wh[1], backgroundColor: '#f00', autoHideMenuBar: true, titleBarStyle: "hidden", resizable: true, minimizable: true, maximizable: true, frame: false, show: false, webPreferences: { contextIsolation: false, //上下文隔离 // nodeIntegration: true, //启用Node集成(是否完整的支持 node) nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, // devTools: false, webSecurity: false, enableRemoteModule: true, //是否启用远程模块(即在渲染进程页面使用remote) } } } // 获取窗口 getWindow(id) { return BrowserWindow.fromId(id) } // 获取全部窗口 getAllWindows() { return BrowserWindow.getAllWindows() } // 创建窗口 createWindows(options) { console.log('------------开始创建窗口...') console.log(options) let args = Object.assign({}, windowsCfg, options) console.log(args) // 判断窗口是否存在 for(let i in this.group) { if(this.getWindow(Number(i)) && this.group[i].route === args.route && !this.group[i].isMultiWindow) { this.getWindow(Number(i)).focus() return } } let opt = this.winOpts([args.width || 800, args.height || 600]) if(args.parentId) { console.log('parentId:' + args.parentId) opt.parent = this.getWindow(args.parentId) } else if(this.main) { console.log(666) } if(typeof args.modal === 'boolean') opt.modal = args.modal if(typeof args.resizable === 'boolean') opt.resizable = args.resizable if(args.backgroundColor) opt.backgroundColor = args.backgroundColor if(args.minWidth) opt.minWidth = args.minWidth if(args.minHeight) opt.minHeight = args.minHeight console.log(opt) let win = new BrowserWindow(opt) console.log('窗口id:' + win.id) this.group[win.id] = { route: args.route, isMultiWindow: args.isMultiWindow, } // 是否最大化 if(args.maximize && args.resizable) { win.maximize() } // 是否主窗口 if(args.isMainWin) { if(this.main) { console.log('主窗口存在') delete this.group[this.main.id] this.main.close() } this.main = win } args.id = win.id win.on('close', () => win.setOpacity(0)) // 打开网址(加载页面) /** * 开发环境: http://localhost:8080 * 正式环境: app://./index.html */ let winURL if (process.env.WEBPACK_DEV_SERVER_URL) { // Load the url of the dev server if in development mode // win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) winURL = args.route ? `http://localhost:8080${args.route}` : `http://localhost:8080`