問題:如何實現輸出Electron的版本號和它的依賴項到你的web頁面上?
答案:在主進程通過Node的全局?process
?對象訪問這個信息是微不足道的。 然而,你不能直接在主進程中編輯DOM,因為它無法訪問渲染器?文檔
?上下文。 它們存在于完全不同的進程!這是將?預加載?腳本連接到渲染器時派上用場的地方。預加載腳本在渲染器進程加載之前加載,并有權訪問兩個 渲染器全局 (例如?window
?和?document
) 和 Node.js 環境。
1.創建預加載腳本?
在項目的src/preload/目錄下
創建一個名為?preload.js
?的新腳本如下:?
const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('electronAPI', {onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value)),setTitle: (title) => ipcRenderer.send('set-title', title)
})
2.在主進程中引入
在主進程的background.js文件中,引入預加載腳本如下:
// 指定預加載腳本webPreferences: {// 啟用上下文隔離contextIsolation: true,// 禁用 Node.js 集成,因為我們將通過預加載腳本來提供所需的功能nodeIntegration: false,// 禁用 remote 模塊,出于安全考慮enableRemoteModule: false,// 設置預加載腳本preload: path.join(__dirname, "preload.js"),},
這里使用了兩個Node.js概念:
- __dirname?字符串指向當前正在執行腳本的路徑 (在本例中,它指向你的項目的根文件夾)。
- path.join?API 將多個路徑聯結在一起,創建一個跨平臺的路徑字符串。
我們使用一個相對當前正在執行JavaScript文件的路徑,這樣您的相對路徑將在開發模式和打包模式中都將有效。
background.js文件?
'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } 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')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定預加載腳本webPreferences: {// 啟用上下文隔離contextIsolation: true,// 禁用 Node.js 集成,因為我們將通過預加載腳本來提供所需的功能nodeIntegration: false,// 禁用 remote 模塊,出于安全考慮enableRemoteModule: false,// 設置預加載腳本preload: path.join(__dirname, "preload.js"),},// webPreferences: {// // Use pluginOptions.nodeIntegration, leave this alone// // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info// nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,// contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染進程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {// // Install Vue Devtools// try {// //await installExtension(VUEJS_DEVTOOLS)// } catch (e) {// console.error('Vue Devtools failed to install:', e.toString())// }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}
?3.在主進程和渲染進程中使用預加載腳本
主進程中使用:
ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染進程消息:`, title);event.reply('update-counter', title)})
?主進程完整腳本文件
'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } 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')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定預加載腳本webPreferences: {// 啟用上下文隔離contextIsolation: true,// 禁用 Node.js 集成,因為我們將通過預加載腳本來提供所需的功能nodeIntegration: false,// 禁用 remote 模塊,出于安全考慮enableRemoteModule: false,// 設置預加載腳本preload: path.join(__dirname, "preload.js"),},// webPreferences: {// // Use pluginOptions.nodeIntegration, leave this alone// // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info// nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,// contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染進程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {// // Install Vue Devtools// try {// //await installExtension(VUEJS_DEVTOOLS)// } catch (e) {// console.error('Vue Devtools failed to install:', e.toString())// }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}
渲染進程中使用:
<template><div><div>接收主進程的消息{{ ShowData }}</div><button @click="sendToMain">Send Message to Main</button></div>
</template><script>
export default {data() {return {ShowData: 0,};},methods: {sendToMain() {const title = Math.round(Math.random() * 100);window.electronAPI.setTitle(title);},},mounted() {// 監聽主進程的回復window.electronAPI.onUpdateCounter((value) => {console.log(`接收主進程的消息:`, value);this.ShowData = value;});},// beforeDestroy() {// // 在組件銷毀前,移除事件監聽器// window.ipcRenderer.removeAllListeners("reply-from-main");// },
};
</script>
注意:開發環境時主進程使用的是軟件編譯后dist_electron目錄下的
preload.js
?預加載文件
?到這里在開發環境就能使用預加載腳本實現主進程和渲染進程通信了。
4.在vue.config.js中進行electron打包配置
如果想在electron打包后的軟件中仍然可以正常使用預加載腳本文件的話,必須在vue.config.js文件中進行相應的打包配置。
pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//項目名,也是生成的安裝文件名,即.exe"copyright": "Copyright ? 2024",//版權信息"win": {//win相關配置// "icon": "./src/assets/icon.ico",//圖標,當前圖標在根目錄下"target": [{"target": "nsis",//利用nsis制作安裝程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一鍵安裝"allowElevation": true, // 允許請求提升。 如果為false,則用戶必須使用提升的權限重新啟動安裝程序。"allowToChangeInstallationDirectory": true, // 允許修改安裝目錄// "installerIcon": "./src/assets/icon.ico",// 安裝圖標// "uninstallerIcon": "./src/assets/icon.ico",//卸載圖標// "installerHeaderIcon": "./src/assets/icon.ico", // 安裝時頭部圖標"createDesktopShortcut": true, // 創建桌面圖標"createStartMenuShortcut": true,// 創建開始菜單圖標"shortcutName": "voloday_test", // 圖標名稱},}},},
vue.config.js文件?
const { defineConfig } = require('@vue/cli-service')
const path = require("path");
console.log(`path.join(__dirname,'preload.js')`, path.join(__dirname,'preload.js'));
module.exports = defineConfig({transpileDependencies: true,publicPath: './',pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//項目名,也是生成的安裝文件名,即.exe"copyright": "Copyright ? 2024",//版權信息"win": {//win相關配置// "icon": "./src/assets/icon.ico",//圖標,當前圖標在根目錄下"target": [{"target": "nsis",//利用nsis制作安裝程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一鍵安裝"allowElevation": true, // 允許請求提升。 如果為false,則用戶必須使用提升的權限重新啟動安裝程序。"allowToChangeInstallationDirectory": true, // 允許修改安裝目錄// "installerIcon": "./src/assets/icon.ico",// 安裝圖標// "uninstallerIcon": "./src/assets/icon.ico",//卸載圖標// "installerHeaderIcon": "./src/assets/icon.ico", // 安裝時頭部圖標"createDesktopShortcut": true, // 創建桌面圖標"createStartMenuShortcut": true,// 創建開始菜單圖標"shortcutName": "voloday_test", // 圖標名稱},}},},})
源碼:GitHub - 1t1824d/elctron29.0.0_node18.19.0_vuecli5.0.8_vue2?