要在index.html 窗口中获取div 元素的innerText(或等效元素),您需要向渲染线程发送一条消息以请求此信息。在此之后,您将需要您的渲染线程将innerText 发送回您的主线程进行处理(保存)。
Electron 的 Inter-Process Communication 有时可能会让人感到困惑,但如果实施得当,它会变得简单而安全。
要了解有关所涉及过程的更多信息,您需要阅读并尝试理解以下链接:
让我们首先构建您的 html 文档。它至少必须包含一个可编辑的<div> 标签和一个“保存”按钮。
index.html(渲染线程)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Test Editor</title>
<style>
#editor {
width: 50vw;
height: 50vh;
}
<style>
</head>
<body>
<div id="content" contenteditable="true"></div>
<input type="button" id="save" value="Save">
</body>
<script src="script.js"></script>
</html>
请参阅Example: A simple but complete rich text editor 了解一些很酷的想法。
现在让我们添加“保存”按钮和 IPC 消息功能。
script.js(渲染线程)
// IIFE (Immediately Invoked Function Expression)
(function() => {
let content = document.getElemetById('content').innerText;
document.getElementById('save').addEventListener('click', saveContent(content));
window.ipcRender.receive('editor:getContent', () => { saveContent(content); });
});
function saveContent(content) {
window.ipcRender.send('editor:saveContent', content);
}
这是您的 main.js 文件,其中包含以下更新。
- 添加 Electron 的
ipcMain 模块。
- 将
win 对象添加到顶级范围,这样它就不会被垃圾回收。
- 侦听来自渲染线程的消息(使用 IFFE)。
- 添加
saveContent() 函数(由您完全充实)。
- 从
new BrowserWindow 行中删除const。
- 从
createWindow() 函数返回win,以便以后可以引用它。
- 更新globalShortcut
ctrl+s函数。
main.js(主线程)
const { app, BrowserWindow, globalShortcut, ipcMain } = require('electron');
const path = require('path');
let win = null;
// IIFE (Immediately Invoked Function Expression)
(function() => {
ipcMain.on('editor:saveContent', (event, content) => { saveContent(content); });
})();
function saveContent(content) {
console.log("saving...");
// Save content...
console.log("saved...");
}
// Create the main window
function createWindow() {
// Adjust a few settings
win = new BrowserWindow({
// What the height and width that you open up to
width: 500,
height: 600,
// Minimun width and height
minWidth: 400,
minHeight: 400,
icon: __dirname + '/icon.png',
// Change the window title
title: "text editor",
webPreferences: {
// Preload so that the javascript can access the text you write
preload: path.join(__dirname, 'preload.js'),
}
});
win.loadFile('index.html');
// Remove that ugly title bar and remove unnecessary keyboard shortcuts
win.removeMenu();
return win;
}
// Create window on ready so that no nasty errors happen
app.on('ready', () => {
// Create the window.
win = createWindow();
// Global shortcut so the user has the ability to exit
globalShortcut.register('ctrl+e', () => {
console.log("exiting...");
app.exit();
});
// Global shortcut to save editable content.
globalShortcut.register('ctrl+s', () => {
console.log('ctrl+s pressed.');
win.webContents.send('editor:getContent');
});
})
// when all windows close this app actually closes
app.on('window-all-closed', () => {
if (process !== 'darwin') app.quit();
})
请注意,我已将文件系统功能的实际保存留给您。请参阅Node.js: fs.writeFile() 了解更多信息。
好的,最后一块拼图是一个有效的preload.js 脚本。这是允许在主线程和渲染线程之间使用白名单通道列表的脚本。
在这里我们添加editor:saveContent 和editor:getContent 频道名称。
preload.js(主线程)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'editor:saveContent'
],
// From main to render.
'receive': [
'editor:getContent'
],
// From render to main and back again.
'sendReceive': []
}
};
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);
}
}
}
);
请注意,我没有在preload 脚本中执行任何所谓的功能。我只管理一个列表
频道名称以及与这些频道名称相关的任何数据的传输。