使用electron时间不是好久,随着使用的深刻慢慢的也遇到一些问题,下面总结一下遇到的问题与你们分享,避免趟坑。javascript
与渲染进程之间的通讯不一样,渲染进程与webview之间的通讯,在webview层经过调用sendToHost
方法来向渲染进程通讯;而在渲染进程测经过webview提供的ipc-message
事件来向webview通讯。具体以下面代码所示:前端
// renderer环境,获取webview,而后注册事件 webview.addEventListener('ipc-message', (event) => { // 经过event.channel的值来判断webview发送的事件名 if (event.channel === 'webview_event_name') { console.log(event.args[0]) // 123 } }) webview.send('renderer_event_name', '456') // webview环境 const {ipcRenderer} = require('electron') ipcRenderer.on('renderer_event_name', (e, message) => { console.log(message); // 456 ipcRenderer.sendToHost('webview_event_name', '123') })
具体来讲,就是在使用new BrowserWindow
时,配置其webPreferences选项的nodeIntegration
值为true,即:java
new BrowserWindow({ webPreferences: { nodeIntegration: true // 注入node模块 } })
这样,第三方网站按照CMD格式加载前端模块时以下所示,node
!function(a, b) { "object" == typeof module && "object" == typeof module.exports ? module.exports = a.document ? b(a, !0) : function(a) { if (!a.document) throw new Error("jQuery requires a window with a document"); return b(a) } : b(a) }(this, fn);
能够看出,若electron窗口配置集成node模块的话,前端模块占用了node关键字module
,致使前端页面的模块成了node的模块,以jQuery为例,依赖jQuery的模块会出现以下错误信息:git
Uncaught ReferenceError: $ is not defined
知道问题所在,解决问题有两种思路:github
不启用node功能,即设置nodeIntegration: false
。这种方式比较粗暴,不能更好的拓展electron应用web
在页面加载模块依赖以前改变module
,以后恢复module指向node模块。api
针对第二种方法,github上有人提出解决方案。咱们在不可控的加载第三方网站时,利用BrowserWindow的前置注入脚本preload
来提供修改module指向,可参考代码以下:app
// renderer var win = new BrowserWindow({ ... webPreferences: { nodeIntegration: true, preload: process.cwd() + '/app/resource/preload.js' } }); // preload.js // electron的BrowserWindow设置nodeIntegration为true时,致使页面能够访问node的module影响页面正常模块引入功能,如jQuery document.addEventListener('DOMNodeInserted', function(event){ // 页面内容加载以前须要引入的一些代码 if (document.head && !document.getElementById('module')) { var script = document.createElement('script'); script.setAttribute('id', 'module'); script.innerHTML = "if (typeof module === 'object') {window.module = module; module = undefined;}" document.head.appendChild(script); } }); document.addEventListener('DOMContentLoaded', function(event) { // 页面内容加载以后须要引入的一些操做 var script = document.createElement('script'); script.innerHTML = `if (window.module) module = window.module;` document.body.appendChild(script); })
BrowserWindow
提供的preload
的配置是为了在页面第一次加载文档以前预先加载js脚本文件,其须要注意3个问题:dom
preload是在脚本加载以前执行,其有三个阶段以下,具体能够参考#217 Electron 深度实践总结:
// --------------------------------------------------- // 第一阶段:在页面加载以前须要执行的相关代码 // ... // ------------------------------------------------------- document.addEventListener('DOMNodeInserted', (event) => { // 第二阶段:页面内容加载以前须要引入的一些代码 // ... }) // ------------------------------------------------------- document.addEventListener('DOMContentLoaded', (event) => { // 第三阶段:页面内容加载以后须要引入的一些操做 // ... }) // -------------------------------------------------------
能够看出:
preload环境
可使用Node API,又能访问DOM、BOM的特殊环境,即便dom文档还未造成以前。