![](/img/trans.png)
[英]Angular & Electron: ipcRenderer - __dirname is not defined
[英]How to import ipcRenderer in vue.js ? __dirname is not defined
我很難理解如何在 .vue 文件中正確導入 ipcRenderer。
我放入 /src/background.js 文件:
webPreferences: {
nodeIntegration:false,
contextIsolation: true, // protects against prototype pollution
preload: path.join(__dirname, "../dist_electron/preload.js"),
}
而且,基於https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration我把 preload.js :
window.ipcRenderer = ipcRenderer
webpack.config.js :
module.exports = {
entry: './src/background.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'background.js'
}
}
為了方便調試,我創建了一個github repo。 你可以從這里 git 克隆 repo: https ://github.com/raphael10-collab/ElectronVueTypeScriptScaffolding.git
執行 yarn -> yarn electron:serve 后你會得到正確的頁面。
但是在 /src/views/Home.vue 中激活此行時:
//從“電子”導入 { ipcRenderer }
你會得到這個錯誤:
Environment Info:
System:
OS: Linux 5.4 Ubuntu 18.04.5 LTS (Bionic Beaver)
CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
Binaries:
Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
Yarn: 1.22.4 - /usr/bin/yarn
npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
Browsers:
Chrome: 85.0.4183.83
Firefox: 79.0
npmPackages:
@vue/babel-helper-vue-jsx-merge-props: 1.0.0
@vue/babel-plugin-transform-vue-jsx: 1.1.2
@vue/babel-preset-app: 4.4.6
@vue/babel-preset-jsx: 1.1.2
@vue/babel-sugar-functional-vue: 1.1.2
@vue/babel-sugar-inject-h: 1.1.2
@vue/babel-sugar-v-model: 1.1.2
@vue/babel-sugar-v-on: 1.1.2
@vue/cli-overlay: 4.4.6
@vue/cli-plugin-babel: ~4.4.0 => 4.4.6
@vue/cli-plugin-e2e-cypress: ~4.4.0 => 4.4.6
@vue/cli-plugin-router: ~4.4.0 => 4.4.6
@vue/cli-plugin-typescript: ~4.4.0 => 4.4.6
@vue/cli-plugin-unit-mocha: ~4.4.0 => 4.4.6
@vue/cli-plugin-vuex: ~4.4.0 => 4.4.6
@vue/cli-service: ~4.4.0 => 4.4.6
@vue/cli-shared-utils: 4.4.6
@vue/component-compiler-utils: 3.2.0
@vue/preload-webpack-plugin: 1.1.2
@vue/test-utils: ^1.0.3 => 1.0.3
@vue/web-component-wrapper: 1.2.0
babel-helper-vue-jsx-merge-props: 2.0.3
typescript: ^3.9.7 => 3.9.7
vue: ^2.6.11 => 2.6.11
vue-class-component: ^7.2.5 => 7.2.5
vue-cli-plugin-electron-builder: ~2.0.0-rc.4 => 2.0.0-rc.4
vue-hot-reload-api: 2.3.4
vue-i18n: ^8.20.0 => 8.20.0
vue-loader: 15.9.3
vue-property-decorator: ^9.0.0 => 9.0.0
vue-router: ^3.2.0 => 3.3.4
vue-style-loader: 4.1.2
vue-template-compiler: ^2.6.11 => 2.6.11
vue-template-es2015-compiler: 1.9.1
vuex: ^3.5.1 => 3.5.1
vuex-class: ^0.3.2 => 0.3.2
npmGlobalPackages:
@vue/cli: 4.4.6
node version: v14.5.0
更新 1)
我嘗試將 webPreferences 設置如下(使用 nodeIntegration:true):
webPreferences: {
nodeIntegration: true,
//contextIsolation: true, // protects against prototype pollution
//preload: path.join(__dirname, "../dist_electron/preload.js"),
},
並得到這個錯誤:
搜索有關此類問題的信息,我發現了這篇文章: 如何解決 fs.existsSync 不是函數通過此鏈接: https ://webpack.js.org/concepts/targets/
但我已經在 webpack.config.js 中指定了目標“節點”:
在 webpack.config.js 中:
module.exports = {
entry: './src/background.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'background.js'
}
}
那么......如何解決這個新問題?
順便說一句,我為什么要放
webPreferences: {
nodeIntegration: true,
}
如果出於安全原因,更安全的是:
webPreferences: {
nodeIntegration:false,
contextIsolation: true, // protects against prototype pollution
preload: path.join(__dirname, "../dist_electron/preload.js"),
}
dist_electron/preload.js :
const {
contextBridge,
ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) =>
func(...args));
}
}
}
);
window.ipcRenderer = ipcRenderer
https://www.electronjs.org/docs/tutorial/security#electron-security-warnings
更新 2)
在 vue.config.js 我放了:
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'dist_electron/preload.js',
// Or, for multiple preload files:
//preload: { preload: 'src/preload.js', otherPreload:
//'src/preload2.js' }
}
}
}
但是當我這樣做時我得到了同樣的錯誤
yarn electron:serve
UncaughtReferenceError: __dirname 未定義
設置 nodeIntegration: true 時(但我更願意將其設置為 false,並使用 preload.js 文件),我得到另一個錯誤(如上):
Uncaught TypeError: fs.existsSync is not a function
如何解決問題? 期待您的熱心幫助
為了將 ipcRenderer 與 Vue CLI 插件 Electron Builder 一起使用,您需要首先設置 electron 以使用 preload.js 文件。
在您的vue.config.js
文件中,您需要像這樣添加preload.js
路徑:
// vue.config.js - project root
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js',
// Or, for multiple preload files:
preload: { preload: 'src/preload.js', otherPreload: 'src/preload2.js' }
}
}
}
接下來,您需要更新您的background.js
文件以在 Web 首選項中使用preload.js
,如下所示:
// src/background.js
const win = new BrowserWindow({
width: 800,
height: 600,
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,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js'),
},
})
注意:
nodeIntegration
是禁用的,contextIsolation
默認是啟用的
完成后,您可以在 src 目錄中創建preload.js
文件。
啟用contextIsolation
后,您需要將contextBridge
與ipcRenderer
一起導入。 然后您可以將ipcRenderer
公開給您的客戶端。
然后將其添加到文件中:
// src/preload.js
import { contextBridge, ipcRenderer } from 'electron'
// Expose ipcRenderer to the client
contextBridge.exposeInMainWorld('ipcRenderer', {
send: (channel, data) => {
let validChannels = ['nameOfClientChannel'] // <-- Array of all ipcRenderer Channels used in the client
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data)
}
},
receive: (channel, func) => {
let validChannels = ['nameOfElectronChannel'] // <-- Array of all ipcMain Channels used in the electron
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args))
}
}
})
注意:您需要確保您的
preload.js
文件位於src
文件夾中,而不是dist_electron
要測試並確保預加載文件正常工作,您還可以在preload.js
文件中創建警報
// src/preload.js
import { contextBridge, ipcRenderer } from 'electron'
// Expose ipcRenderer to the client
contextBridge.exposeInMainWorld('ipcRenderer', {
send: (channel, data) => {
let validChannels = ['nameOfClientChannel'] // <-- Array of all ipcRenderer Channels used in the client
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data)
}
},
receive: (channel, func) => {
let validChannels = ['nameOfElectronChannel'] // <-- Array of all ipcMain Channels used in the electron
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args))
}
}
})
alert("It Worked!") // Remove this line once you confirm it worked
當您確認您的預加載腳本工作正常后,您可以從您的 vue 應用程序訪問ipcRenderer
。
像這樣:
// src/App.vue
<template>
\\ Some html
</template>
<script>
export default {
name: "App",
methods: {
test(){
window.ipcRenderer.send(channel, args...) // or any other ipcRenderer method you want to invoke
}
};
</script>
在電子中,您可以收聽這些事件
// background.js
ipcMain.on(channel, (event, args) => {
// Do stuff
});
資料來源:
為了將 ipcRenderer 與 Vue CLI 插件 Electron Builder 一起使用,您需要首先設置 electron 以使用 preload.js 文件。
在您的vue.config.js
文件中,您需要像這樣添加preload.js
路徑:
// vue.config.js - project root
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js',
// Or, for multiple preload files:
preload: { preload: 'src/preload.js', otherPreload: 'src/preload2.js' }
}
}
}
接下來,您需要更新您的background.js
文件以在 Web 首選項中使用preload.js
,如下所示:
// src/background.js
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/configuration.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
+ preload: path.join(__dirname, 'preload.js')
}
})
完成后,您可以在 src 目錄中創建preload.js
文件
然后將其添加到文件中:
// src/preload.js
import { ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer
注意:您需要確保您的
preload.js
文件位於src
文件夾中,而不是dist_electron
要測試並確保預加載文件正常工作,您還可以在preload.js
文件中創建警報
// src/preload.js
import { ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer
alert("It Worked!") // Remove this line once you confirm it worked
當您確認您的預加載腳本工作正常后,您可以從您的 vue 應用程序訪問 ipcRenderer。
像這樣:
// src/App.vue
<template>
\\ Some html
</template>
<script>
export default {
name: "App",
methods: {
test(){
window.ipcRenderer.send(channel, args...) // or any other ipcRenderer method you want to invoke
}
};
</script>
資料來源:
對我有用的是將電子窗口的contextIsolation
設置為false
。
因此,在您的main.js
中,無論您創建BrowserWindow
,它都會如下所示:
const win = new BrowserWindow({
webPreferences: {
contextIsolation: false,
preload: path.join(__dirname, 'preload.js'),
},
})
然后在preload.js
你可以簡單地做
const { ipcRenderer } = require('electron')
window.ipcRenderer = ipcRenderer
然后你就可以在你的 vue 代碼的任何地方訪問ipcRenderer
了。
似乎在當前版本的電子contextIsolation
中默認為true
,這使得preload.js
看到的window
與您的 vue 應用程序看到的窗口不同。
您需要將nodeIntegration
設置為true
。
這在渲染器進程(即前端)中啟用了 NodeJ,因此您可以在 Vue 代碼中使用 fs(文件系統)和其他僅限 NodeJ 的功能。
由於 ipcRenderer 也需要 NodeJs 的環境(__dirname 只是 NodeJs 的全局變量),因此需要激活它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.