我理解為什么最好不要在渲染器行程中公開 Node 或 Electron 的完整 API。而且我了解如何使用預加載腳本僅公開這些 API 的必要子集。
但我不明白的是如何使用這個模型撰寫渲染器邏輯。
我的 mainBrowswerWindow腳本renderer.js必須包含幾乎所有的 UI 邏輯,監聽所有window事件并相應地修改頁面的 DOM。
通常,我想以模塊化的方式構建這個龐大的腳本,但是 Electron 的孤立背景關系意味著Node 的模塊系統將不可用。Electron 檔案建議使用諸如webpack或parcel可能是解決方案的打包工具。但沒有提供示例。
(而且我注意到在VSCode和 Electron 自己的Fiddle應用程式的源代碼中,他們似乎只是聳了聳肩并啟用 Node 集成。)
但在理想情況下,這實際上是如何作業的?
例如,每次我想測驗運行應用程式時,我是否應該有一個腳本來將我的所有src內容壓縮為 3 個腳本 - main.min.js、rederer.min.js和preload.min.js?把它們放在一個app目錄中?然后在從那里運行電子之前復制我的靜態內容?
是這個想法,還是我沒有得到什么?
uj5u.com熱心網友回復:
您不需要使用webpack或parcel來構建安全的 Electron 應用程式。這些用于捆綁您的代碼,而不是保護它。
很難為 Electron 找到好的、最佳實踐的設計檔案。正如您已經發現的那樣,在不自己實作的情況下設定nodeIntegration為的建議可能會令人困惑。false
nodeIntegrationtrue如果您不在渲染中加載任何遠程內容,則可以設定為。參考:不要為遠程內容啟用 Node.js 集成。我總是將我的腳本設定為false并利用我的preload.js腳本在主行程和渲染行程之間通信/傳輸資料。
關于“如何使用此模型撰寫渲染器邏輯”,當您退后一步并查看更廣泛的圖片時,希望它會變得更加清晰。
您必須在行程中考慮 Electron (盡管我傾向于使用術語執行緒)。主行程和渲染行程。
如您所知,您使用 IPC 在行程之間進行通信。在主行程和渲染行程中,您可以使用事件。在您的主行程中使用 Node 的事件時,模塊變得緊密耦合的問題被消除了。
現在,preload.js劇本...
我看到很多人試圖直接訪問硬編碼到他們preload.js腳本中的具體實作。在很短的時間內,這可能會變得非常復雜和令人困惑。
我采取了一種非常不同的方法。我的整個專案只使用一個 preload.js腳本。我的預加載腳本的目的不是定義/實作具體模型,而是preload.js純粹將腳本用作溝通渠道。IE:在主行程和渲染行程之間來回發送“事件”的通道名稱(和可選資料)。讓主行程中的腳本處理具體的 Electron / Node 實作,讓渲染行程中的腳本處理 html 互動性。
主要流程
主行程包含 Electron 的核心和 Node.js
您可以將代碼拆分為邏輯塊并使用 Node 的require函式匯入它們。請記住,一旦呼叫它們,它們就會被快取。他們也有效地擁有自己的范圍,這很棒。
為了減輕嘗試計算路徑的負擔,只需使用 Node 的path.join(...)模塊。
使用 Node 的事件在您的應用程式模塊之間進行通信。
使用 Electron 的ipcMain.on(...)和ipcMain.handle(...)偵聽來自渲染行程的 IPC 事件,并使用contents.send(...)將 IPC 事件發送到您的特定渲染行程。
渲染程序
渲染程序包含您的 html 視圖、使您的 html 視圖具有互動性的 Javascript,當然還有與 CSS 相關的 html 視圖。
在這里使用 ES6 模塊來分離你的代碼。import將它們放入您的 html Javascript 檔案中,記住只使用export您公開可用的函式。
You can reference all paths as relative paths. Any build tools you may use should be able to handle this when setup correctly.
Use Electron's ipcRender.on(...) to listen for IPC events from the main process and ipcRender.send(...) and ipcRender.invoke(...) to send IPC events to the main process.
To use these above commands easily, setup your preload.js script like so.
preload.js (main process)
// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'message:fromRender' // Example channel name
],
// From main to render.
'receive': [
'message:fromMain' // Example channel name
],
// From render to main and back again.
'sendReceive': [
'message:fromRenderAndBackAgain' // Example channel name
]
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
Building your channel name whitelist in your preload.js script provides one source of truth. Including the same (one and only) preload.js script in every created window becomes easy and error free.
If you need for me to add to this answer the use of the preload.js script in the main and render processes just let me know.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/445948.html
