我也遇到过同样的问题,但发现了一个很长的问题。
原因
看看这一行:
(<any>window).require
此行搜索require()
全局窗口对象中的方法,这是一个 NodeJS 函数,因此如果您使用 Electron 版本 > 5,则不会在运行时注入,因为webPreferences -> nodeIntegration
BrowserWindow 类的属性默认设置为 false。
解决方案
有两种解决方案:
- 设置
nodeIntegration: true
并且contextIsolation: false
该应用程序将按预期工作但此黑客存在安全问题。正如这个答案中所引用的:
Electron 应用程序很棒,因为我们可以使用节点,但这种力量是一把双刃剑。如果我们不小心,我们会通过我们的应用程序让某人访问节点,并且使用节点的不良行为者可能会损坏您的机器或删除您的操作系统文件(除其他外,我想)。
- 使用
contextBridge
和 preload.js:这是从上面的答案和这个问题的其他答案中得出的。
我将介绍一个使用 Angular 的解决方法。
在main.js中webPreferences
创建的mainWindow
时候,进行如下修改:
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, "preload.js")
}
在相同的目录中main.js
,创建一个preload.js
文件并在其中添加以下代码(您可以省略receive()
该用例的声明,因为它不是必需的)。
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 = ["openModal"];
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));
}
}
}
);
PS:添加此代码的原因已在参考答案中提到,因此我不会在这里重复。
现在,在运行时,电子将在全局对象中注入window.api.send()
和方法。如果您尝试直接在 Angular 组件中访问它们,linter 将给出错误,因为它们未在标准窗口对象上定义。为了解决这个问题,我们将创建一个 Angular 服务并注入我们的应用程序。该服务将引用在运行时创建的浏览器的窗口对象,并添加了上述两个功能。window.api.receive()
window
创建一个WindowRefService
并添加以下代码:
窗口参考服务.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class WindowRefService {
getWindow(): any {
return window;
}
constructor() { }
get nativeWindow(): Window{
return this.getWindow();
}
}
不要忘记在 AppModule 中注册服务:
...
import { WindowRefService } from './window-ref.service';
...
@NgModule{
...
providers: [WindowRefService]
}
之后将其注入您的组件中:
import { WindowRefService } from './window-ref.service';
...
private _window:any;
constructor(windowRef: WindowRefService){
this._window = windowRef.nativeWindow;
}
...
//openModal function
openModal(){
console.log("Open a modal");
this._window.api.send("openModal", /* data to be sent, if any*/);
}
删除private ipc: IpcRenderer | any;
构造函数中的 和其他现有代码,因为它不是必需的。