所以,我对Electron很陌生,想建立一个桌面应用程序。但我一直遇到一些问题,特别是在让渲染器和主进程进行通信方面。我知道IPC和远程的概念,还有这个关于我无法在第一时间使用它们的问题。在决定在这里发帖之前,我试着浏览了很多相关问题。更具体的说,我有一个表单(HTML),需要填写并保存到本地数据库(sqlite)中,我原本计划从HTML中访问数据库,但却无法实现。因此,我去做了一个renderer.js,并把它作为一个脚本包含到HTML中,也失败了(不能使用'require')--在这两次过程中我都打开了nodeintegration。以下是其他的解决方案,目前还没有成功。
一个preload.js脚本。根据我的想象,我可以在这里包含我的'require'语句,但是当我试图访问DOM元素时,问题就来了,因为我必须注册IPC事件。
在了解到Browserify工具可以捆绑所有必要的模块,并将其提供给渲染器后,我最终选择了Browserify工具。在这里,我也是按照所述的程序(https:/github.combrowserifybrowserify#usage),但就是无法让它工作,同时又出现了一大堆新的错误(TypeError: fs.exencesSync is not a function, RangeError),而且我仍然在浏览器中得到可怕的'require'is not defined error。
我现在基本上陷入了僵局,不知道该何去何从。如果有必要,我可以在这里分享一些代码。任何帮助都将是非常感激的。
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();}
注册.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(renderer): require没有定义。
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,以及像我提到的那样,创建一个新的renderer文件,并将其作为脚本链接到HTML之外,我没有做任何不同的事情。这样就成功了,现在主程序和UI可以通过IPC通信了。由于这仅仅是一个桌面应用程序,我希望与开启nodeIntegration相关的任何安全问题都不会有太大问题。