无法让我的主要进程和渲染进程以电子方式进行通信
Cannot get my main and renderer processes to communicate in electron
所以,我是 Electron 的新手,想构建一个桌面应用程序。但是我一直 运行 遇到问题,特别是在让渲染器和主进程进行通信方面。我知道 IPC 和远程概念,这与我一开始无法使用它们有关。在决定在这里 post 之前,我尝试浏览了很多相关问题。更具体地说,我有一个表格 (HTML) 需要填写并保存到本地数据库 (sqlite),我最初计划从 HTML 中访问但不能。因此,我选择了 renderer.js 并将其作为脚本包含在 HTML 中,这也失败了(无法使用 'require')- 我在这两次中都打开了节点集成。以下是迄今为止尝试过但没有成功的其他解决方案:
A preload.js 脚本:根据我的想象,我可以在此处包含我的 'require' 语句,但是当我尝试访问 DOM 元素,因为我必须注册 IPC 事件
在了解到 browserify 工具可以捆绑所有必要的模块并使它们可供渲染器使用后,我最终选择了 browserify 工具。在这里,我也遵循了规定的程序(https://github.com/browserify/browserify#usage),但无法让它与抛出的一大堆新错误一起工作(TypeError:fs.existsSync 不是函数,RangeError)和我仍然在浏览器中遇到可怕的 'require' is not defined 错误。
我现在基本上陷入了僵局,不知道该何去何从。如有必要,我可以在这里分享一些代码。任何帮助将不胜感激。
main.js
const MainDAO = require('./dao/appDAO')
const {ipcMain} = require('electron')
const electron = require('electron')
const { app, BrowserWindow, Menu } = require('electron')
const path = require('path')
//const template = require('./js/templates')
//const employeeReg = require('./assets/js/employeeReg')
const dbPath = 'Model/lunaDb'
const dialog = electron.dialog
let lunaDB = new MainDAO(dbPath);
/************************************************************************** */
/*************Login Page
****************************************************************************/
function createSignInWindow() {
// Create the browser window.
let signIn = new BrowserWindow({
width: 800, height: 520, icon: __dirname + '/img/logo.png',
webPreferences: {
nodeIntegration: true,
}
});
//Load signin window
signIn.loadFile('view/signin.html')
//remove menu list
signIn.removeMenu();}
register.html:这是我第一次想将表单数据保存到sqlite数据库的地方
<script src="../dist/bundle.js"></script>
<script>
var currentTab = 0; // Current tab is set to be the first tab (0)
showTab(currentTab); // Display the current tab
function showTab(n) {
// This function will display the specified tab of the form ...
var x = document.getElementsByClassName("tab");
x[n].style.display = "block";
// ... and fix the Previous/Next buttons:
if (n == 0) {
document.getElementById("prevBtn").style.display = "none";
} else {
document.getElementById("prevBtn").style.display = "inline";
}
if (n == (x.length - 1)) {
document.getElementById("nextBtn").innerHTML = "Submit And Again";
} else {
document.getElementById("nextBtn").innerHTML = "Next";
}
// ... and run a function that displays the correct step indicator:
fixStepIndicator(n)
}
function nextPrev(n) {
// This function will figure out which tab to display
var x = document.getElementsByClassName("tab");
// Exit the function if any field in the current tab is invalid:
if (n == 1 && !validateForm()) return false;
// Hide the current tab:
x[currentTab].style.display = "none";
// Increase or decrease the current tab by 1:
currentTab = currentTab + n;
// if you have reached the end of the form... :
if (currentTab >= x.length) {
window.location.reload();
//...the form gets submitted:
alert("Succesfully Added");
// document.getElementById("regForm").submit();
return false;
}
// Otherwise, display the correct tab:
showTab(currentTab);
}
function validateForm() {
// This function deals with validation of the form fields
var x, y, i, valid = true;
x = document.getElementsByClassName("tab");
z = x[currentTab].getElementsByClassName("needs-validation");
y = x[currentTab].getElementsByTagName("input");
var validation = Array.prototype.filter.call(z, function (form) {
form.classList.add("was-validated");
switch (currentTab) {
case 0:
var name = document.querySelector('#inputName');
var email = document.querySelector('#inputEmail');
var phone = document.querySelector('#inputPhoneNo')
if ((email.checkValidity() == false) || (name.checkValidity() == false) || (name.checkValidity() == false)) {
valid = false;
}
break;
case 1:
var name = document.querySelector('#inputContactName');
var phone = document.querySelector('#inputContactPhoneNo');
if ((name.checkValidity() == false) || (phone.checkValidity() == false)) {
valid = false;
}
break;
case 2:
var position = document.querySelector('#inputPosition');
var salary = document.querySelector('#inputBasicSalary');
var hiringDate = document.querySelector('#inputHiringDate')
if ((position.checkValidity() == false) || (salary.checkValidity() == false) || (hiringDate.checkValidity() == false)) {
valid = false;
}
break
default:
break;
}
});
if (valid) {
document.getElementsByClassName("step")[currentTab].className += " finish";
}
return valid; // return the valid status
}
function fixStepIndicator(n) {
// This function removes the "active" class of all steps...
var i, x = document.getElementsByClassName("step");
for (i = 0; i < x.length; i++) {
x[i].className = x[i].className.replace(" active", "");
}
//... and adds the "active" class to the current step:
x[n].className += " active";
}
</script>
<script src="../assets/js/register.js"></script>
register.js(渲染器):未定义要求
const ipc = require('electron').ipcRenderer
const submitEmplForm = document.getElementById('nextBtn')
preload.js :当我尝试在此处访问 DOM 组件时,它抱怨为空,这就是为什么我尝试添加 require('./register)...但没有'也不行
const { ipcRenderer } = require('electron')
const emp = require('./register')
const _setImmediate = setImmediate
const _clearImmediate = clearImmediate
process.once('loaded', () => {
global.setImmediate = _setImmediate
global.clearImmediate = _clearImmediate
})
const submitEmplForm = document.querySelector('nextBtn')
submitEmplForm.addEventListener('click', function (event) {
ipcRenderer.send('asynchronous-message', 'ping')
})
ipcRenderer.on('asynchronous-message', function (event, args) {
event.preventDefault()
console.log('event is ' + event)
console.log(args)
})
当然还有来自 browserify 的 bundle.js 文件。
仅供参考,你有没有做过类似下面的事情
const electron = require('electron');
const {app , BrowserWindow , Menu , ipcMain } = electron;
//用于通讯的ipcMain
let mainWindow;
let addWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({webPreferences: {
nodeIntegration:true}});
mainWindow.loadURL(`file://${__dirname}/main.html`);
mainWindow.on('closed', () => app.quit());
const mainMenu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(mainMenu);
});
然后在节点端的 ipc main 上
ipcMain.on('todo:add', (event , todo) => {
console.log(todo);
});
在你的 html 那边
<script>
const electron = require('electron');
const {ipcRenderer}= electron; -- to communicate
ipcRenderer.on('todo:add', (event , todo) => {
// my code
});
</script>
你做过这样的事吗?
能否分享代码,有助于指出其他问题
在仔细创建一个新文件后,我终于设法从 renderer.js 文件中访问所需的模块和 DOM 元素,从最低限度开始并逐步添加更多代码以隔离问题出在哪里。老实说,除了摆脱预加载脚本之外,我没有做任何不同的事情,再次打开 nodeIntegration 并像我提到的那样,创建一个新的渲染器文件和 link 到 HTML 作为剧本。这样就成功了,现在 main 和 UI 可以通过 IPC 进行通信。由于这只是一个桌面应用程序,我希望与打开 nodeIntegration 相关的任何安全问题都不会成为大问题。
显然,在您的 preload.js
中,您为渲染器进程提供了两个永远不会 defined/declared 的全局变量:setImmediate
和 clearImmediate
。您应该将 ipcRenderer
本身声明为全局变量:
process.once('loaded', () => {
global.ipcRenderer = ipcRenderer
})
然后 ipcRenderer
在使用您的 preload.js
启动的所有渲染器进程中可用。
所以,我是 Electron 的新手,想构建一个桌面应用程序。但是我一直 运行 遇到问题,特别是在让渲染器和主进程进行通信方面。我知道 IPC 和远程概念,这与我一开始无法使用它们有关。在决定在这里 post 之前,我尝试浏览了很多相关问题。更具体地说,我有一个表格 (HTML) 需要填写并保存到本地数据库 (sqlite),我最初计划从 HTML 中访问但不能。因此,我选择了 renderer.js 并将其作为脚本包含在 HTML 中,这也失败了(无法使用 'require')- 我在这两次中都打开了节点集成。以下是迄今为止尝试过但没有成功的其他解决方案:
A preload.js 脚本:根据我的想象,我可以在此处包含我的 'require' 语句,但是当我尝试访问 DOM 元素,因为我必须注册 IPC 事件
在了解到 browserify 工具可以捆绑所有必要的模块并使它们可供渲染器使用后,我最终选择了 browserify 工具。在这里,我也遵循了规定的程序(https://github.com/browserify/browserify#usage),但无法让它与抛出的一大堆新错误一起工作(TypeError:fs.existsSync 不是函数,RangeError)和我仍然在浏览器中遇到可怕的 'require' is not defined 错误。
我现在基本上陷入了僵局,不知道该何去何从。如有必要,我可以在这里分享一些代码。任何帮助将不胜感激。
main.js
const MainDAO = require('./dao/appDAO')
const {ipcMain} = require('electron')
const electron = require('electron')
const { app, BrowserWindow, Menu } = require('electron')
const path = require('path')
//const template = require('./js/templates')
//const employeeReg = require('./assets/js/employeeReg')
const dbPath = 'Model/lunaDb'
const dialog = electron.dialog
let lunaDB = new MainDAO(dbPath);
/************************************************************************** */
/*************Login Page
****************************************************************************/
function createSignInWindow() {
// Create the browser window.
let signIn = new BrowserWindow({
width: 800, height: 520, icon: __dirname + '/img/logo.png',
webPreferences: {
nodeIntegration: true,
}
});
//Load signin window
signIn.loadFile('view/signin.html')
//remove menu list
signIn.removeMenu();}
register.html:这是我第一次想将表单数据保存到sqlite数据库的地方
<script src="../dist/bundle.js"></script>
<script>
var currentTab = 0; // Current tab is set to be the first tab (0)
showTab(currentTab); // Display the current tab
function showTab(n) {
// This function will display the specified tab of the form ...
var x = document.getElementsByClassName("tab");
x[n].style.display = "block";
// ... and fix the Previous/Next buttons:
if (n == 0) {
document.getElementById("prevBtn").style.display = "none";
} else {
document.getElementById("prevBtn").style.display = "inline";
}
if (n == (x.length - 1)) {
document.getElementById("nextBtn").innerHTML = "Submit And Again";
} else {
document.getElementById("nextBtn").innerHTML = "Next";
}
// ... and run a function that displays the correct step indicator:
fixStepIndicator(n)
}
function nextPrev(n) {
// This function will figure out which tab to display
var x = document.getElementsByClassName("tab");
// Exit the function if any field in the current tab is invalid:
if (n == 1 && !validateForm()) return false;
// Hide the current tab:
x[currentTab].style.display = "none";
// Increase or decrease the current tab by 1:
currentTab = currentTab + n;
// if you have reached the end of the form... :
if (currentTab >= x.length) {
window.location.reload();
//...the form gets submitted:
alert("Succesfully Added");
// document.getElementById("regForm").submit();
return false;
}
// Otherwise, display the correct tab:
showTab(currentTab);
}
function validateForm() {
// This function deals with validation of the form fields
var x, y, i, valid = true;
x = document.getElementsByClassName("tab");
z = x[currentTab].getElementsByClassName("needs-validation");
y = x[currentTab].getElementsByTagName("input");
var validation = Array.prototype.filter.call(z, function (form) {
form.classList.add("was-validated");
switch (currentTab) {
case 0:
var name = document.querySelector('#inputName');
var email = document.querySelector('#inputEmail');
var phone = document.querySelector('#inputPhoneNo')
if ((email.checkValidity() == false) || (name.checkValidity() == false) || (name.checkValidity() == false)) {
valid = false;
}
break;
case 1:
var name = document.querySelector('#inputContactName');
var phone = document.querySelector('#inputContactPhoneNo');
if ((name.checkValidity() == false) || (phone.checkValidity() == false)) {
valid = false;
}
break;
case 2:
var position = document.querySelector('#inputPosition');
var salary = document.querySelector('#inputBasicSalary');
var hiringDate = document.querySelector('#inputHiringDate')
if ((position.checkValidity() == false) || (salary.checkValidity() == false) || (hiringDate.checkValidity() == false)) {
valid = false;
}
break
default:
break;
}
});
if (valid) {
document.getElementsByClassName("step")[currentTab].className += " finish";
}
return valid; // return the valid status
}
function fixStepIndicator(n) {
// This function removes the "active" class of all steps...
var i, x = document.getElementsByClassName("step");
for (i = 0; i < x.length; i++) {
x[i].className = x[i].className.replace(" active", "");
}
//... and adds the "active" class to the current step:
x[n].className += " active";
}
</script>
<script src="../assets/js/register.js"></script>
register.js(渲染器):未定义要求
const ipc = require('electron').ipcRenderer
const submitEmplForm = document.getElementById('nextBtn')
preload.js :当我尝试在此处访问 DOM 组件时,它抱怨为空,这就是为什么我尝试添加 require('./register)...但没有'也不行
const { ipcRenderer } = require('electron')
const emp = require('./register')
const _setImmediate = setImmediate
const _clearImmediate = clearImmediate
process.once('loaded', () => {
global.setImmediate = _setImmediate
global.clearImmediate = _clearImmediate
})
const submitEmplForm = document.querySelector('nextBtn')
submitEmplForm.addEventListener('click', function (event) {
ipcRenderer.send('asynchronous-message', 'ping')
})
ipcRenderer.on('asynchronous-message', function (event, args) {
event.preventDefault()
console.log('event is ' + event)
console.log(args)
})
当然还有来自 browserify 的 bundle.js 文件。
仅供参考,你有没有做过类似下面的事情 const electron = require('electron');
const {app , BrowserWindow , Menu , ipcMain } = electron;
//用于通讯的ipcMain
let mainWindow;
let addWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({webPreferences: {
nodeIntegration:true}});
mainWindow.loadURL(`file://${__dirname}/main.html`);
mainWindow.on('closed', () => app.quit());
const mainMenu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(mainMenu);
});
然后在节点端的 ipc main 上
ipcMain.on('todo:add', (event , todo) => {
console.log(todo);
});
在你的 html 那边
<script>
const electron = require('electron');
const {ipcRenderer}= electron; -- to communicate
ipcRenderer.on('todo:add', (event , todo) => {
// my code
});
</script>
你做过这样的事吗?
能否分享代码,有助于指出其他问题
在仔细创建一个新文件后,我终于设法从 renderer.js 文件中访问所需的模块和 DOM 元素,从最低限度开始并逐步添加更多代码以隔离问题出在哪里。老实说,除了摆脱预加载脚本之外,我没有做任何不同的事情,再次打开 nodeIntegration 并像我提到的那样,创建一个新的渲染器文件和 link 到 HTML 作为剧本。这样就成功了,现在 main 和 UI 可以通过 IPC 进行通信。由于这只是一个桌面应用程序,我希望与打开 nodeIntegration 相关的任何安全问题都不会成为大问题。
显然,在您的 preload.js
中,您为渲染器进程提供了两个永远不会 defined/declared 的全局变量:setImmediate
和 clearImmediate
。您应该将 ipcRenderer
本身声明为全局变量:
process.once('loaded', () => {
global.ipcRenderer = ipcRenderer
})
然后 ipcRenderer
在使用您的 preload.js
启动的所有渲染器进程中可用。