我正在尝试创建一个具有多个"页面"的Electron应用程序。
就我而言,我正在尝试制作一个带有不同部分的侧边栏的应用程序。单击某个部分后,主窗口的内容将更改以呈现该部分的相应内容。
我是JS的新手,如果这是一个愚蠢的问题,我很抱歉,但是到目前为止,每当我尝试转到应用程序的某个部分时,在一切再次加载之前,我都会看到一秒钟的白色闪光屏幕。
示例:https://i.stack.imgur.com/weWWA.gif
我知道这与 Electron 重新加载 Chrome 引擎有关,但是我怎样才能做到当单击某个部分时,内容会自动显示而没有任何"闪烁"或奇怪的事情?
基本上:如何使用Electron构建具有大量组件的GUI?
我的index.html
代码是:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Rupture Tools</title>
<link rel="stylesheet" href="./photon/css/photon.min.css">
</head>
<body>
<div class="window">
<div class="window-content">
<div class="pane-group">
<div class="pane-sm sidebar">
<nav class="nav-group">
<h5 class="nav-group-title">1 Click Generator</h5>
<a class="nav-group-item active">
<span class="icon icon-home"></span>
Dashboard
</a>
<a href="accounts.html">
<span class="nav-group-item">
<span class="icon icon-user-add"></span>
Accounts
</span>
</a>
<span class="nav-group-item">
<span class="icon icon-cloud-thunder"></span>
Activity
</span>
<span class="nav-group-item">
<span class="icon icon-check"></span>
Check Scores
</span>
<span class="nav-group-item">
<span class="icon icon-cog"></span>
Settings
</span>
<span class="nav-group-item">
<span class="icon icon-help-circled"></span>
Help/FAQ
</span>
</nav>
</div>
<div class="pane">Home</div>
</div>
</div>
</div>
</body>
</html>
请帮忙!我对此一无所知,一直在到处寻找。我来自Python,那里没有任何前端开发或GUI设计。谢谢!
这里有一个"某种"解决方案,但它使用了一种叫做 Sass 的东西,据我所知,使用 React 或 Angular 这样的东西更好。我从来没有使用过其中任何一个。
Electron应用程序与Web应用程序非常相似。正如您所注意到的,在 HTML 文档之间导航的传统方式不适用于应用程序。这就是为什么现在将 Web 应用程序开发为单页应用程序 (SPA) 的原因。它只是意味着在用户导航时使用JavaScript手动加载和替换页面的某些部分。有几种方法可以实现这一点,但下面是如何为您的代码完成此操作的示例:
// Get all the navigation links to an array
const naviLinks = Array.from(document.getElementsByClassName("nav-group-item"));
const contentEl = document.getElementsByClassName("pane")[0];
naviLinks.forEach((linkEl) => {
// Listen click event for the navigation link
linkEl.addEventListener("click", e => {
// Prevent default behavior for the click-event
e.preventDefault();
// Get the path to page content file
const href = linkEl.getAttribute("href");
if (href) {
// Use node.js fs-module to read the file
const fs = require("fs");
fs.readFile(href, (err, data) => {
if (err) {
throw err;
}
// show the selected page
contentEl.innerHTML = "";
contentEl.insertAdjacentHTML("beforeend", data);
})
}
})
})
请注意,页面内容 HTML 文件(帐户.html等)应仅包含"窗格"div
的内容。在主进程中创建BrowserWindow
-对象时,还需要传递nodeIntegration:true
,因此您可以使用require
加载fs
-module:
new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
}
如果页面内容文件很大,导航可能看起来很慢,因为每次单击都会读取文件并呈现页面。一种有助于实现此目的的优化是在页面加载时读取文件并在屏幕外创建页面元素,然后交换click
事件上的元素。或者,您可以将页面内容放在<template>
元素中并交换它们。如果您有兴趣,我会将这些留给您自己尝试。
有大量的JavaScript框架可以帮助你创建SPA。目前一些流行的是React,Angular和Vue。"如何构建包含大量组件的 GUI?">是前端JavaScript框架可以回答的问题之一,但当然有一个学习曲线。当你觉得需要开始将你的GUI拆分为可重用或分层的组件时,研究一下这些JavaScript框架可能是个好主意。
不久前我做了一些代码来做到这一点(不幸的是它相当复杂,但实现起来应该不难)。
您将此功能放在每个页面上:
function loadPageWithIframe (url) {
var hiddenPage = document.createElement("iframe");
hiddenPage.setAttribute("src", url);
hiddenPage.style.display = 'none';
document.body.appendChild(hiddenPage);
hiddenPage.onload = function () {
var frameDocument = hiddenPage.document;
if (hiddenPage.contentDocument) {
frameDocument = hiddenPage.contentDocument;
} else if (hiddenPage.contentWindow) {
frameDocument = hiddenPage.contentWindow.document;
}
document.open();
document.write(frameDocument.documentElement.innerHTML);
document.close();
window.history.pushState("", document.title, url.replace('https://' + window.location.hostname, ''));
}
}
你的电子文件中的这段代码:
mainWindow.webContents.on('will-navigate', function (evt, url) {
evt.preventDefault();
mainWindow.webContents.executeJavaScript('loadPageWithIframe("' + url + '");');
});
如果你正确地输入代码,它应该会自动工作,没有任何额外的代码。
其工作方式是,当您要转到 url 时调用loadPageWithIframe
函数,然后它创建一个 iframe 并加载页面,从 iframe 复制所有 html,并用 iframe HTML 覆盖当前页面的 HTML。
但是,与其在每次点击时手动调用loadPageWithIframe
函数,不如使用 Electron 的will-navigate
事件让我们知道它要转到另一个页面,然后调用loadPageWithIframe
(这是我发布的电子代码的目的)。
我希望这对:)有所帮助