1.Electron 12中的remote
模块已弃用,将在Electron 14中拆除.由@electronic/remote
模块替代
npm install --save @electron/remote
在主线程中使用:
注意:主进程要进行如下设置
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,
}
require(’@electron/remote/main’).initialize()// 开启。这个必须得有。否则也创建不了
require("@electron/remote/main").enable(webContents)
示例:
'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()
// 在应用程序准备就绪之前,必须注册方案
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("bilibili.com/")
}
// DesktopToolWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '#/ztdada/desktoptool');
DesktopToolWindow.setIgnoreMouseEvents(false)
DesktopToolWindow.setSkipTaskbar(true)
// DesktopToolWindow.loadURL("bilibili.com/")
//DesktopToolWindow.loadFile('../src/pages/DesktopToolPage/index.vue')
DesktopToolWindow.on('closed', () => {
DesktopToolWindow = null
})
}
在渲染进程使用(.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选项.
nklayman.github.io/vue-cli-plu…
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/")
}
示例:
生产环境中electron加载路由页面