开发者问题收集

当将电子事件与 Vue 结合使用时,如何修复未定义的 __dirname?

2020-07-07
18103

我使用 nklayman/vue-cli-plugin-electron-builder 创建了一个使用 Vue/Vuex 准备的电子应用程序。它附带文件 main.jsbackground.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)

知道我做错了什么吗?

3个回答

为了解决这个问题,我在项目根目录中创建了一个文件 vue.config.js ,内容为

module.exports = {
    pluginOptions: {
        electronBuilder: {
            nodeIntegration: true
        }
    }
}
ajthinking
2020-08-02

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 代替。

参考: https://www.electronjs.org/docs/api/ipc-main

Helper function
2020-12-04

您可以应用此帖子中描述的解决方案 如何在 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 文件

rafalimaz
2021-09-02