如何创建具有多个部分的Electron应用程序

时间:2019-04-27 07:31:21

标签: javascript navigation electron

我正在尝试创建一个具有多个“页面”的Electron应用程序。

就我而言,我正在尝试制作一个带有不同部分的侧边栏的应用程序。单击某个部分后,主窗口的内容将更改为呈现该部分的适当内容。

我是JS的新手,如果这是一个愚蠢的问题,对不起,但是截至目前,每当我尝试进入该应用程序的某个部分时,在所有内容再次加载之前,我都会获得一秒钟闪烁的白色屏幕。

示例:https://i.imgur.com/qOyuYsz.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之类的解决方案更好。我从没用过。

2 个答案:

答案 0 :(得分:0)

我前一段时间编写了一些代码来完成此操作(不幸的是,它相当复杂,但是实现起来并不难)。

您在每个页面上都放置了此功能:

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并覆盖当前页面的HTML使用iframe HTML。

但是,除了可以在每次单击时手动调用loadPageWithIframe函数之外,您还可以使用Electron的will-navigate事件让我们知道它要转到另一个页面,然后调用loadPageWithIframe(这是是我发布的电子代码的目的。

我希望能对您有所帮助:)

答案 1 :(得分:0)

电子应用程序与网络应用程序非常相似。如您所见,在HTML文档之间进行导航的传统方式不适用于应用程序。这就是为什么如今将Web应用程序开发为single-page applications(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文件(accounts.html等)应仅包含“窗格” div的内容。在主流程中创建nodeIntegration:true对象时,您还需要传递BrowserWindow,因此您可以使用require来加载fs-module:

new BrowserWindow({
    webPreferences: {
        nodeIntegration: true
    }
}

如果页面内容文件很大,则导航可能会变慢,因为每次单击都会读取文件并呈现页面。一种帮助解决此问题的优化方法是在页面加载时在屏幕外读取文件并创建页面元素,然后仅在click事件上交换元素。或者,您可以将页面内容放入<template>元素中并交换它们。如果您有兴趣,我会把这些留给您自己尝试。

有许多JavaScript框架可以帮助您创建SPA。目前一些受欢迎的是React,Angular和Vue。 “如何构建具有许多组件的GUI?” 是前端JavaScript框架可以回答的问题之一,但是当然还有学习的余地。当您需要将GUI分为可重用或分层的组件时,考虑使用这些JavaScript框架可能是个好主意。