使用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文檔還未造成以前。