当将电子事件与 Vue 结合使用时,如何修复未定义的 __dirname?
我使用
nklayman/vue-cli-plugin-electron-builder
创建了一个使用 Vue/Vuex 准备的电子应用程序。它附带文件
main.js
、
background.js
,包括 Vue 组件起点。但我无法让事件正常工作。以下尝试在渲染时产生
Uncaught ReferenceError: __dirname is not defined
(编译正常)。
组件:Splash.vue
<template>
<div @click="open">open</div>
</template>
<script>
const { ipcMain } = require('electron')
export default {
methods: {
open()
{
ipcMain.on('my-open-event', (event, arg) => {
console.log(event, arg)
})
}
}
}
</script>
background.js
import { app, protocol, BrowserWindow } from 'electron'
...
app.on('my-open-event', async () => {
try {
"Will call some executable here";
} catch (e) {
console.error(e)
}
})
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount('#app')
完整错误:
Uncaught ReferenceError: __dirname is not defined
at eval (webpack-internal:///./node_modules/electron/index.js:4)
at Object../node_modules/electron/index.js (chunk-vendors.js:1035)
at __webpack_require__ (app.js:849)
at fn (app.js:151)
at eval (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/Splash.vue?vue&type=script&lang=js&:6)
at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/Splash.vue?vue&type=script&lang=js& (app.js:986)
at __webpack_require__ (app.js:849)
at fn (app.js:151)
at eval (webpack-internal:///./src/components/Splash.vue?vue&type=script&lang=js&:2)
at Module../src/components/Splash.vue?vue&type=script&lang=js& (app.js:1271)
知道我做错了什么吗?
为了解决这个问题,我在项目根目录中创建了一个文件
vue.config.js
,内容为
module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: true
}
}
}
Electron 中有两个进程,主进程和渲染进程。您的 Vue 组件是渲染进程。为了在这两个进程之间进行通信,您需要进程间通信。因此,在您的例子中,您可能需要在
background.js
中使用
ipcMain
定义一个通道。您可以编写类似以下内容的内容:
ipcMain.on("my-custom-channel", (event, args) => handleEvent(event, args));
然后在您的 Vue 组件中,您将使用渲染进程 ipcRendere,例如:
import { ipcRenderer } from "electron";
export default {
methods: {
open() {
ipcRenderer.send('my-custom-channel', "hello from Vue!")
}
}
}
要点是:您不能将
app.on
用于自定义事件。
app.on
处理预定义的 electron 事件。请使用
ipcMain.on
代替。
您可以应用此帖子中描述的解决方案 如何在 vue.js 中导入 ipcRenderer? __dirname 未定义
通过这种方式,您可以从 vue 文件调用 window.ipcRenderer.send(channel, args...)。
只需确保在 vue.config.js 上配置 preload.js:
// vue.config.js - project root
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js' //make sure you have this line added
}
}
}
另一个解决方案可以在这里找到 https://medium.com/swlh/how-to-safely-set-up-an-electron-app-with-vue-and-webpack-556fb491b83 并且它使用 __static 来引用预加载文件,而不是在 vue.config.js 上对其进行配置。为了使其正常工作,您可以在 BrowserWindow 构造函数中禁用预加载 es-lint 警告:
// eslint-disable-next-line no-undef
preload: path.resolve(__static, 'preload.js')
并确保在 /public 文件夹中添加了 preload.js 文件