1.Electron 12中的remote
模塊已棄用,將在Electron 14中拆除.由@electronic/remote
模塊替代
npm install --save @electron/remote
在主線程中使用:
注意:主進程要進行如下設置
require(’@electron/remote/main’).initialize()// 開啟。這個必須得有。否則也創建不了 require("@electron/remote/main").enable(webContents)
示例:
在渲染進程使用(.vue文件):
注意:在vue文件中直接require("electron")會報錯,需要這樣引入
const { require } = window; const { ipcRenderer } = require("electron"); const { BrowserWindow } = require("@electron/remote");
或者這樣引入
const { ipcRenderer } = window.require("electron");
const { BrowserWindow } = window.require("@electron/remote");
示例:
2.@electron/remote經過上面配置在開發環境可以正常使用,但打包時,還需做以下配置,否則打包后運行軟件會報錯
官網上是這樣解釋:
本機模塊受支持,並且應在不進行任何配置的情況下工作,前提是啟用了節點集成。如果出現錯誤,可能需要將本機依賴項設置為外部網頁包(打開新窗口)。應該會自動找到它,但可能不會。為此,請使用externals選項.
https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#table-of-contents
externals: ['@electron/remote'],
nodeModulesPath: ['../../node_modules', './node_modules'],
在vue.config.js文件中:
pluginOptions: { 'style-resources-loader': { preProcessor: 'scss', patterns: [path.resolve(__dirname, './src/assets/globalscss/*.scss'), ] }, electronBuilder: { externals: ['@electron/remote'], nodeModulesPath: ['../../node_modules', './node_modules'], builderOptions: { productName: "volodya", appId: 'volodya', win: { "target": [ "nsis" ], icon: 'src/assets/img/app.png', "requestedExecutionLevel": "requireAdministrator", 'legalTrademarks': 'http://www.baidu.com/' }, "nsis": { "installerIcon": "src/assets/ico/app.ico", "uninstallerIcon": "src/assets/ico/app.ico", "uninstallDisplayName": "CPU Monitor", "license": "src/assets/ico/license.html", "oneClick": false, "allowToChangeInstallationDirectory": true, "displayLanguageSelector": true, }, "mac": { "icon": "src/assets/ico/app.icns", // 應用程序圖標 "artifactName": "volodya", // 應用程序包名 "target": [ "dmg", "zip" ] }, 'dmg': { 'title': 'volodya', 'icon': 'src/assets/ico/app.icns', 'contents': [{ 'x': 110, 'y': 150 }, { 'x': 240, 'y': 150, 'type': 'link', 'path': '/Applications' } ], 'window': { 'x': 400, 'y': 400 } } }, }, },
3.在創建windows系統托盤時,let tray = null要設置為全局變量,否則會被回收機制清除,導致系統托盤自動消失的問題。
注意: __dirname=== dist_electron ,__static === public,例如:app.png圖片在vue-cli4創建的vue項目的public/img
文件下,在electron項目里使用 path.join(__static, 'img/app.png')
示例:
/******* 創建系托盤 *******/ let tray = null let CreateTray = () => { tray = new Tray(path.join(__static, 'img/app.png')); const contextMenu = Menu.buildFromTemplate([{ label: '設置', click: () => {} //打開相應頁面 }, { label: 'Item1', type: 'radio' }, { label: 'Item2', type: 'radio', checked: true }, { label: '退出', click: () => { if (!!mainWindow) { mainWindow.destroy() mainWindow = null } if (!!DesktopToolWindow) { DesktopToolWindow.destroy() DesktopToolWindow = null } } }, //我們需要在這里有一個真正的退出(這里直接強制退出) ]) tray.setToolTip('My托盤測試') tray.setContextMenu(contextMenu) tray.on('click', () => { //我們這里模擬桌面程序點擊通知區圖標實現打開關閉應用的功能 console.log("mainWindow.isVisible(", mainWindow.isVisible()) //isMinimized() mainWindow.show() }) }
調用:
CreateTray()
4.vue,router,electron結合使用
注意:路由要用hash模式,不可用history模式
router/index.js
/** * Модуль роутера приложения */ import Vue from 'vue'; import VueRouter from 'vue-router'; import initListners from './initListners'; import listners from './listners'; import Home from '@/views/Home/index' Vue.use(VueRouter) const routes = [ /* { path: '/', redirect: '/ztdada/home', }, */ { path: '/ztdada/login', name: 'Login', component: () => import ('@/views/Login/index'), meta: { Title: "登錄", } }, { path: '/', name: 'Home', component: Home, // component: () => // import ('@/views/Home/index'), meta: { Title: "首頁", } }, { path: '/ztdada/desktoptool', name: 'DesktopTool', component: () => import ('@/views/DesktopTool/index'), meta: { Title: "首頁", } }, { path: '*', component: () => import ('@/views/Error/index'), hidden: true } ]; const router = new VueRouter({ // mode: 'history', // base: process.env.BASE_URL, routes }) export default initListners(router, listners);
在electron項目中使用:
background.js
“/”根路徑頁面"http://192.168.252.1:8080/#/"使用
if (process.env.WEBPACK_DEV_SERVER_URL) { // 如果處於開發模式,請加載開發服務器的url await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL) if (!process.env.IS_TEST) mainWindow.webContents.openDevTools() } else { createProtocol('app') // 加載索引,非開發中的html //mainWindow.loadURL('app://./index.html') mainWindow.loadURL('app://./index.html') }
路由頁面"http://192.168.252.1:8080/#/ztdada/desktoptool"使用
if (process.env.WEBPACK_DEV_SERVER_URL) { // 如果處於開發模式,請加載開發服務器的url await DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool') // if (!process.env.IS_TEST) //DesktopToolWindow.webContents.openDevTools() } else { createProtocol('app') // 加載索引,非開發中的html await DesktopToolWindow.loadURL('app://./index.html#/ztdada/desktoptool') //await DesktopToolWindow.loadURL("https://bilibili.com/") }
示例:

'use strict' import { app, protocol, BrowserWindow, ipcMain, Menu, Tray } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' //import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' const isDevelopment = process.env.NODE_ENV !== 'production' const path = require('path'); require('@electron/remote/main').initialize() console.log(",__static, __dirname", __static, __dirname) // 在應用程序准備就緒之前,必須注冊方案 protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]) let mainWindow = null let tray = null /******* 創建系托盤 *******/ let CreateTray = () => { tray = new Tray(path.join(__static, 'img/app.png')); const contextMenu = Menu.buildFromTemplate([{ label: '設置', click: () => {} //打開相應頁面 }, { label: 'Item1', type: 'radio' }, { label: 'Item2', type: 'radio', checked: true }, { label: '退出', click: () => { if (!!mainWindow) { mainWindow.destroy() mainWindow = null } if (!!DesktopToolWindow) { DesktopToolWindow.destroy() DesktopToolWindow = null } } }, //我們需要在這里有一個真正的退出(這里直接強制退出) ]) tray.setToolTip('My托盤測試') tray.setContextMenu(contextMenu) tray.on('click', () => { //我們這里模擬桌面程序點擊通知區圖標實現打開關閉應用的功能 console.log("mainWindow.isVisible(", mainWindow.isVisible()) //isMinimized() mainWindow.show() }) } async function createWindow() { // 創建瀏覽器窗口。 mainWindow = new BrowserWindow({ width: 710, height: 492, resizable: false, frame: false, transparent: false, webPreferences: { nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false contextIsolation: process.env.ELECTRON_NODE_INTEGRATION, enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION, } }) mainWindow.setSkipTaskbar(false) mainWindow.flashFrame(true) console.log("process.env.WEBPACK_DEV_SERVER_URL", process.env.WEBPACK_DEV_SERVER_URL) if (process.env.WEBPACK_DEV_SERVER_URL) { // 如果處於開發模式,請加載開發服務器的url await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL) if (!process.env.IS_TEST) mainWindow.webContents.openDevTools() } else { createProtocol('app') // 加載索引,非開發中的html //mainWindow.loadURL('app://./index.html') mainWindow.loadURL('app://./index.html') } mainWindow.once("ready-to-show", () => { mainWindow.show(); }) // mainWindow.setMenu(null) /******* 引入遠程模塊 *******/ require("@electron/remote/main").enable(mainWindow.webContents); mainWindow.on('closed', (event) => { mainWindow = null; }); // mainWindow.on('close', (event) => { // event.preventDefault(); // }); // mainWindow.on('show', (event) => { // event.preventDefault(); // }) // mainWindow.on('hide', (event) => { // event.preventDefault(); // }) } // 關閉所有窗口后退出。 app.on('window-all-closed', () => { // 在macOS上,應用程序及其菜單欄很常見 // 在用戶使用Cmd+Q明確退出之前保持活動狀態 if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { //在macOS上,當 //已單擊停靠圖標,並且沒有其他窗口打開。 if (BrowserWindow.getAllWindows().length === 0) createWindow() }) //此方法將在Electron完成后調用 //初始化並准備好創建瀏覽器窗口。 //某些API只能在此事件發生后使用。 app.on('ready', async() => { if (isDevelopment && !process.env.IS_TEST) { // 安裝視圖開發工具 try { //await installExtension(VUEJS_DEVTOOLS) } catch (e) { console.error('Vue Devtools failed to install:', e.toString()) } } createWindow() /******* 創建系托盤 *******/ CreateTray() /******* 監聽渲染進程通信 *******/ ipcMain.on('HomePage', (event, arg) => { console.log(arg) DesktopTool() mainWindow.resizable = true mainWindow.transparent = false mainWindow.minimize(); event.reply('HomePage-reply', "我是主進程傳過去的參數") }) ipcMain.on('DesktopTool', (event, arg) => { console.log(arg) mainWindow.resizable = true mainWindow.transparent = false mainWindow.show(); event.reply('DesktopTool-reply', "我是主進程傳過去的參數") }) // ipcMain.on('CloseClick', (event, arg) => { console.log(arg) mainWindow.resizable = true mainWindow.transparent = false mainWindow.minimize(); event.reply('CloseClick-reply', "我是CloseClick-reply傳過去的參數") }) }) // 在開發模式下,根據父進程的請求干凈地退出。 if (isDevelopment) { if (process.platform === 'win32') { process.on('message', (data) => { if (data === 'graceful-exit') { app.quit() } }) } else { process.on('SIGTERM', () => { app.quit() }) } } /******* 以下是渲染進程 *******/ // 開啟DesktopToolWindow新窗口 let DesktopToolWindow = null function DesktopTool() { if (!!DesktopToolWindow) { DesktopToolWindow.show() } else { CreateDesktopToolWindow() } } async function CreateDesktopToolWindow() { DesktopToolWindow = new BrowserWindow({ width: 160, height: 160, parent: null, resizable: false, frame: false, transparent: true, alwaysOnTop: true, webPreferences: { nodeIntegration: !process.env.ELECTRON_NODE_INTEGRATION, ///process.env.ELECTRON_NODE_INTEGRATION===false contextIsolation: process.env.ELECTRON_NODE_INTEGRATION, enableRemoteModule: !process.env.ELECTRON_NODE_INTEGRATION, } }) if (process.env.WEBPACK_DEV_SERVER_URL) { // 如果處於開發模式,請加載開發服務器的url await DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool') // if (!process.env.IS_TEST) //DesktopToolWindow.webContents.openDevTools() } else { createProtocol('app') // 加載索引,非開發中的html await DesktopToolWindow.loadURL('app://./index.html#/ztdada/desktoptool') //await DesktopToolWindow.loadURL("https://bilibili.com/") } // DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool'); DesktopToolWindow.setIgnoreMouseEvents(false) DesktopToolWindow.setSkipTaskbar(true) // DesktopToolWindow.loadURL("https://bilibili.com/") //DesktopToolWindow.loadFile('../src/pages/DesktopToolPage/index.vue') DesktopToolWindow.on('closed', () => { DesktopToolWindow = null }) }