vue+electron實現(xiàn)創(chuàng)建多窗口及窗口間的通信(實施方案)
一、前言
對于一個桌面應(yīng)用來說,有時候單獨一個窗口用戶使用起來會不太方便,比方說寫日報或者查看文件等,若是在同一窗口內(nèi),我只能做一件事,不能邊預(yù)覽文件,邊去查看聊天消息內(nèi)容等。又或者是多個應(yīng)用間相互關(guān)聯(lián)的需要同步查看的事件,這都是極其不方便的。因此我們可以將某些集成到electron軟件中的應(yīng)用或者某些界面用單獨的窗口打開(以下稱為獨立窗口)。
二、實施方案
1.創(chuàng)建多窗口
首先我們從electron官網(wǎng)中找到創(chuàng)建窗口的方法,electron官網(wǎng)的BrowserWindow,接下來我們就簡單寫一個獨立窗口的創(chuàng)建。這個窗口可以打開外部應(yīng)用也可以是應(yīng)用內(nèi)部。
// windows/CreateIndependentWindow.js import { BrowserWindow, globalShortcut, ipcMain } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' // 關(guān)于這個插件,可以看下前幾天我寫的解決electron白屏那篇文章 import CreateProcessLoadingPage from './CreateProcessLoadingPage' /** * 必傳參數(shù) * outUrl 外部鏈接 * or * inUrl 內(nèi)部鏈接 * windowTitle 頁面標(biāo)題 注意:此值不可重復(fù) */ const CreateIndependentWindow = ({ ...data }, win) => { const obj = { // 窗口的大小可以通過傳進來的參數(shù)控制 height: data.height || 640, width: data.width || 1024, show: false, // 初始是否可顯示 center: true, // 窗口是否可以進入全屏狀態(tài) fullscreenable: false, closable: true, // 窗口是否可關(guān)閉 resizable: true, // 禁止改變主窗口尺寸 webPreferences: { nodeIntegration: true, // 啟用Node integration webSecurity: false, webviewTag: true, // 允許在頁面內(nèi)使用webview標(biāo)簽 enableRemoteModule: true, // 允許渲染進程使用remote模塊 nodeIntegrationInWorker: true, // 在Web工作器中啟用了Node集成 // 允許在子頁面(iframe)或子窗口(child window)中集成Node.js nodeIntegrationInSubFrames: true } } // 這里創(chuàng)建窗口實例 const independentWindow = new BrowserWindow(obj) // 注冊全局快捷鍵-打開開發(fā)者工具(方便查看問題) globalShortcut.register('CommandOrControl+alt+shift+l', () => { independentWindow.webContents.openDevTools() }) // 設(shè)置窗口名稱 independentWindow.setTitle(data.windowTitle || '人脈旺') // 這里將當(dāng)前窗口的唯一id,存入全局變量,以容易區(qū)分多個獨立窗口 // 變量聲明下方說明 global.sharedObject.independentWindow.set(data.windowTitle, independentWindow.webContents.id) // 聲明打開頁面的url let winURL = '' // /IndependentWindow這個路由是在渲染進程創(chuàng)建的承載外部鏈接的獨立窗口的頁面 if (process.env.WEBPACK_DEV_SERVER_URL) { // 判斷若為開發(fā)環(huán)境 // independentWindow.webContents.openDevTools() winURL = process.env.WEBPACK_DEV_SERVER_URL + '#/' + (data.inUrl ? data.inUrl : 'IndependentWindow') } else { createProtocol('app') winURL = 'app://./index.html#' + (data.inUrl ? data.inUrl : '#/IndependentWindow') } // 這里是為了獲取拼接需要傳入到頁面的參數(shù) const param = Object.keys(data).reduce((pre, cue) => { return data[cue] ? `${pre}${pre === '?' ? '' : '&'}${cue}=${data[cue]}` : pre }, '?') // 使用loadURL方法將頁面注入到窗口 independentWindow.loadURL(winURL + param) // 若參數(shù)設(shè)置開啟最大化窗口 if (data.maxSize) { independentWindow.maximize() } // 加載頁面loading CreateProcessLoadingPage(independentWindow, data) independentWindow.on('close', (e) => { globalShortcut.unregister('CommandOrControl+alt+shift+l') global.sharedObject.independentWindow.delete(data.windowTitle) setTimeout(() => { if (!independentWindow.isDestroyed() && independentWindow) { independentWindow.destroy() } }, 100) }) global['independentWindow-' + independentWindow.webContents.id] = independentWindow } export default CreateIndependentWindow
之后我們在主進程中做一個監(jiān)聽,用來創(chuàng)建獨立窗口
ipcMain.on('createOtherWindow', (e, data) => { // type窗口類型,data 參數(shù) const name = data.windowTitle // 判斷當(dāng)前窗口是否已經(jīng)存在, 存在的話 直接喚起 if (global.sharedObject.independentWindow.has(name)) { const id = global.sharedObject.independentWindow.get(name) global['independentWindow-' + id].show() } else { CreateIndependentWindow(data, win) } })
這里我們記得聲明一下存儲獨立窗口id的變量
// background.js // 多窗口數(shù)據(jù)存儲 global.sharedObject = { independentWindow: new Map(), }
之后我們在渲染進程創(chuàng)建一個頁面,用來展示外部鏈接頁面
<template> <div class="independent-window"> <webview id="myWebView" :src="outUrl" style="display:inline-flex; width:100%; height:100%" allowpopups></webview> </div> </template> <script> export default { name: 'IndependentWindow', data () { return { outUrl: '', } }, created () { this.outUrl = this.$route.query.outUrl }, mounted () { this.eventHandler() }, methods: { // 監(jiān)聽打開webview控制臺的快捷鍵 eventHandler () { const webview = document.querySelector('#myWebView') // 用于查看webview內(nèi)第三方應(yīng)用問題,快捷鍵打開webview的開發(fā)者工具 window.addEventListener('keydown', e => { if (e.altKey && e.ctrlKey && e.shiftKey && e.keyCode === 190) { webview.openDevTools() } }) } } } </script> <style lang="less" scoped> .independent-window { width: 100%; height: 100%; } </style>
綜上,我們就創(chuàng)建了一個獨立窗口,這個獨立窗口可以打開項目內(nèi)頁面又或者第三方外部鏈接窗口。
2.多窗口間的通信
electron官方文檔給我們提供了關(guān)于多個窗口間通訊的方法, 對于多窗口間的通訊,多是指渲染進程間的通訊。 這里我們可以使用ipcRenderer.sendTo()這個方法,來進行多窗口建的通信。詳見官方文檔說明
ipcRenderer.sendTo(webContentsId, channel, ...args)
? 以下是官方文檔內(nèi)容
webContentsId
numberchannel
string...args
any[]
通過 channel
發(fā)送消息到帶有 webContentsId
的窗口.
這里就用到了我們之前在global.sharedObject.independentWindow
中存儲的各個窗口的id。 劃重點一定是窗口實例的webContentsId
的id,而不是窗口的id,別問我怎么知道的,問也不說??????。
// 窗口1中 const remote = window.require('electron').remote // 通過窗口名獲取窗口id const id = remote.getGlobal('sharedObject').independentWindow.get('窗口名windowTitle') ipcRenderer.sendTo(id, '約定的通信協(xié)議', 參數(shù)) // ===========================-.-=========== // 在另一個窗口中 ipcRenderer.on('約定的通信協(xié)議', (e, url) => { //做你想做的 })
這樣我們就實現(xiàn)多窗口渲染進程間的通訊。
三、后記
多窗口的場景有人多,有時候情況可能會很復(fù)雜,我建議可以將那些特殊作用的窗口,單獨創(chuàng)建一個,而不是都放到通用的獨立窗口中,這樣管理起來會很方便。
到此這篇關(guān)于vue+electron實現(xiàn)創(chuàng)建多窗口及窗口間的通信的文章就介紹到這了,更多相關(guān)vue electron多窗口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
antd upload上傳組件如何獲取服務(wù)端返回數(shù)據(jù)
這篇文章主要介紹了antd upload上傳組件如何獲取服務(wù)端返回數(shù)據(jù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Vue3+vite路由配置優(yōu)化(自動化導(dǎo)入)
這篇文章主要介紹了Vue3+vite路由配置優(yōu)化(自動化導(dǎo)入),需要的朋友可以參考下2023-09-09使用vue-router在Vue頁面之間傳遞數(shù)據(jù)的方法
這篇文章主要介紹了使用vue-router在Vue頁面之間傳遞數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07vue使用formData時候傳遞參數(shù)是個空值的情況處理
這篇文章主要介紹了vue使用formData時候傳遞參數(shù)是個空值的情況處理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05Vue el-table組件如何實現(xiàn)將日期格式化
這篇文章主要介紹了Vue el-table組件如何實現(xiàn)將日期格式化問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04vue+element-ui+axios實現(xiàn)圖片上傳
這篇文章主要為大家詳細介紹了vue+element-ui+axios實現(xiàn)圖片上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08