vue+electron實(shí)現(xiàn)創(chuàng)建多窗口及窗口間的通信(實(shí)施方案)
一、前言
對于一個(gè)桌面應(yīng)用來說,有時(shí)候單獨(dú)一個(gè)窗口用戶使用起來會(huì)不太方便,比方說寫日報(bào)或者查看文件等,若是在同一窗口內(nèi),我只能做一件事,不能邊預(yù)覽文件,邊去查看聊天消息內(nèi)容等。又或者是多個(gè)應(yīng)用間相互關(guān)聯(lián)的需要同步查看的事件,這都是極其不方便的。因此我們可以將某些集成到electron軟件中的應(yīng)用或者某些界面用單獨(dú)的窗口打開(以下稱為獨(dú)立窗口)。
二、實(shí)施方案
1.創(chuàng)建多窗口
首先我們從electron官網(wǎng)中找到創(chuàng)建窗口的方法,electron官網(wǎng)的BrowserWindow,接下來我們就簡單寫一個(gè)獨(dú)立窗口的創(chuàng)建。這個(gè)窗口可以打開外部應(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)于這個(gè)插件,可以看下前幾天我寫的解決electron白屏那篇文章 import CreateProcessLoadingPage from './CreateProcessLoadingPage' /** * 必傳參數(shù) * outUrl 外部鏈接 * or * inUrl 內(nèi)部鏈接 * windowTitle 頁面標(biāo)題 注意:此值不可重復(fù) */ const CreateIndependentWindow = ({ ...data }, win) => { const obj = { // 窗口的大小可以通過傳進(jìn)來的參數(shù)控制 height: data.height || 640, width: data.width || 1024, show: false, // 初始是否可顯示 center: true, // 窗口是否可以進(jìn)入全屏狀態(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, // 允許渲染進(jìn)程使用remote模塊 nodeIntegrationInWorker: true, // 在Web工作器中啟用了Node集成 // 允許在子頁面(iframe)或子窗口(child window)中集成Node.js nodeIntegrationInSubFrames: true } } // 這里創(chuàng)建窗口實(shí)例 const independentWindow = new BrowserWindow(obj) // 注冊全局快捷鍵-打開開發(fā)者工具(方便查看問題) globalShortcut.register('CommandOrControl+alt+shift+l', () => { independentWindow.webContents.openDevTools() }) // 設(shè)置窗口名稱 independentWindow.setTitle(data.windowTitle || '人脈旺') // 這里將當(dāng)前窗口的唯一id,存入全局變量,以容易區(qū)分多個(gè)獨(dú)立窗口 // 變量聲明下方說明 global.sharedObject.independentWindow.set(data.windowTitle, independentWindow.webContents.id) // 聲明打開頁面的url let winURL = '' // /IndependentWindow這個(gè)路由是在渲染進(jìn)程創(chuàng)建的承載外部鏈接的獨(dú)立窗口的頁面 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
之后我們在主進(jìn)程中做一個(gè)監(jiān)聽,用來創(chuàng)建獨(dú)立窗口
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) } })
這里我們記得聲明一下存儲(chǔ)獨(dú)立窗口id的變量
// background.js // 多窗口數(shù)據(jù)存儲(chǔ) global.sharedObject = { independentWindow: new Map(), }
之后我們在渲染進(jìn)程創(chuàng)建一個(gè)頁面,用來展示外部鏈接頁面
<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控制臺(tái)的快捷鍵 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)建了一個(gè)獨(dú)立窗口,這個(gè)獨(dú)立窗口可以打開項(xiàng)目內(nèi)頁面又或者第三方外部鏈接窗口。
2.多窗口間的通信
electron官方文檔給我們提供了關(guān)于多個(gè)窗口間通訊的方法, 對于多窗口間的通訊,多是指渲染進(jìn)程間的通訊。 這里我們可以使用ipcRenderer.sendTo()這個(gè)方法,來進(jìn)行多窗口建的通信。詳見官方文檔說明
ipcRenderer.sendTo(webContentsId, channel, ...args)
? 以下是官方文檔內(nèi)容
webContentsId
numberchannel
string...args
any[]
通過 channel
發(fā)送消息到帶有 webContentsId
的窗口.
這里就用到了我們之前在global.sharedObject.independentWindow
中存儲(chǔ)的各個(gè)窗口的id。 劃重點(diǎn)一定是窗口實(shí)例的webContentsId
的id,而不是窗口的id,別問我怎么知道的,問也不說??????。
// 窗口1中 const remote = window.require('electron').remote // 通過窗口名獲取窗口id const id = remote.getGlobal('sharedObject').independentWindow.get('窗口名windowTitle') ipcRenderer.sendTo(id, '約定的通信協(xié)議', 參數(shù)) // ===========================-.-=========== // 在另一個(gè)窗口中 ipcRenderer.on('約定的通信協(xié)議', (e, url) => { //做你想做的 })
這樣我們就實(shí)現(xiàn)多窗口渲染進(jìn)程間的通訊。
三、后記
多窗口的場景有人多,有時(shí)候情況可能會(huì)很復(fù)雜,我建議可以將那些特殊作用的窗口,單獨(dú)創(chuàng)建一個(gè),而不是都放到通用的獨(dú)立窗口中,這樣管理起來會(huì)很方便。
到此這篇關(guān)于vue+electron實(shí)現(xiàn)創(chuàng)建多窗口及窗口間的通信的文章就介紹到這了,更多相關(guān)vue electron多窗口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
antd upload上傳組件如何獲取服務(wù)端返回?cái)?shù)據(jù)
這篇文章主要介紹了antd upload上傳組件如何獲取服務(wù)端返回?cái)?shù)據(jù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Vue3+vite路由配置優(yōu)化(自動(dòng)化導(dǎo)入)
這篇文章主要介紹了Vue3+vite路由配置優(yōu)化(自動(dòng)化導(dǎo)入),需要的朋友可以參考下2023-09-09使用vue-router在Vue頁面之間傳遞數(shù)據(jù)的方法
這篇文章主要介紹了使用vue-router在Vue頁面之間傳遞數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07vue使用formData時(shí)候傳遞參數(shù)是個(gè)空值的情況處理
這篇文章主要介紹了vue使用formData時(shí)候傳遞參數(shù)是個(gè)空值的情況處理,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05vue實(shí)現(xiàn)表格數(shù)據(jù)的增刪改查
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)表格數(shù)據(jù)的增刪改查,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Vue el-table組件如何實(shí)現(xiàn)將日期格式化
這篇文章主要介紹了Vue el-table組件如何實(shí)現(xiàn)將日期格式化問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04vue+element-ui+axios實(shí)現(xiàn)圖片上傳
這篇文章主要為大家詳細(xì)介紹了vue+element-ui+axios實(shí)現(xiàn)圖片上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08