我们回到了电子鼠尾草的最新部分。由于本系列更多地是关于设置的,所以我只会走这么远,因为构建应用程序本身并没有真正与Electron的工作相链接。
。构架?
当我刚开始使用电子时,我没有考虑使用JavaScript框架。在大多数情况下,我将PHP用于我的网络开发,因此并没有想到这样的框架可能很有用。
我想构建的应用程序还可以做更多的事情,而不仅仅是将项目添加到我可以编辑的列表中。它需要扩展;因此,我用一个不错的侧边栏和一个主栏构建了第一页...并意识到每次添加新页面时都需要复制侧边栏。
使用PHP时,您将构建页面 index.php ,该页面包含侧栏和一个空的主体,该主栏将填充有require
-或include
函数。您将包含哪些文件取决于当前位置(URI)。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Site</title>
</head>
<body>
<header>
<h1>Hello World</h1>
</header>
<aside>
<nav>
<ul>
<li>navitem</li>
<li>navitem</li>
<li>navitem</li>
<li>navitem</li>
</ul>
</nav>
</aside>
<main>
<?include 'path_of_file'?>
</main>
</body>
</html>
但没有php,所以没有html-cinclude。
我耸了耸肩,而不是寻找可以帮助我的NPM软件包,或者寻找像Svelte这样的框架;我决定尝试使用Vanilla JavaScript进口。它有效,有点。
布局
首先在/front/logic 和一个新文件 app.js 中创建一个新文件夹类。
然后将 app.js 文件链接为模块。
/front/index.html
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My App</title>
<link rel="stylesheet" href="styles/reset.css">
<link rel="stylesheet" href="styles/main.css">
<!-- right here -->
<script type="module" src="logic/app.js"></script>
</head>
很棒,检查连接是否在上次记录值来检查:
/front/logic/app.js
console.log(E_system.mode);
console.log(E_system.platform);
没有破裂?太好了,让我们看看,我们希望它能起作用吗?
好吧,当我单击导航中的一个按钮时;内容应切换出来。
我希望能够分别将内容包含在标题,主和页脚中,以免打破我的主布局。因此,让我们建立一个导航,并在我们的体内包含一些插槽
/front/index.html
<body>
<nav id="feature-nav" class="c-wrapper">
<ul>
<li>
<button sheet="home">
<span>Home</span>
</button>
</li>
<li>
<button sheet="todo">
<span>Todo</span>
</button>
</li>
<li>
<button sheet="tracker">
<span>Schema</span>
</button>
</li>
</ul>
</nav>
<div id="app-interface">
<header>
<content-slot></content-slot>
</header>
<main>
<content-slot></content-slot>
</main>
<footer>
<content-slot></content-slot>
</footer>
</div>
</body>
您可以看到我在所有按钮中添加了我称为sheet
的属性。我还创建了一个文件夹/front/shay ,并添加了一些html文件,名称与这些属性值相对应。
当然,可以将aria标签添加到按钮中。或在ul
上方添加一个跳过的按钮,但是这些功能在此检查系列中有点超出范围。
我希望床单是普通的旧html文件;我想要三个可以用JS Dom-Api来定位的容器,然后像通常一样编写内容。
/front/sheets/home.html
<header-content>
<h1>Home</h1>
</header-content>
<main-content>
my content
</main-content>
<footer-content>
my footer
</footer-content>
JS
类称为page_loader
,只是被导入并调用。 is_ready
方法检查我们的index.html是否具有所有需要工作的元素; activate()
方法启用按钮单击。
import { D$ } from "./fn/dev.js";
import { page_loader } from "./classes/loader.js";
console.log(E_system.mode);
console.log(E_system.platform);
//? Load Pager
{
const page = new page_loader();
if (page.is_ready()) {
D$(console.log, "Page Loader Ready");
page.activate();
} else D$(console.warn, "Page Loader not Ready");
}
它通过使用fetch-api和domparser对象来工作。
单击按钮时,课程检查其链接到哪个表并获取文件。
返回纯文本串;传递给Domparser。此JS-Object能够将我们的普通字符串转换为HTML。
然后,我们使用良好的旧dom-api查询我们的内容障碍
(<header-content>
<main-content>
<footer-content>
)
最后,这只是从我们的index.html中删除旧内容并粘贴新内容以获得我们的最终结果的问题。
辅助功能;
我做了一些助手功能,并将它们保存在文件/front/logic/fn/dev.js 和/em>和/front/logic/fn/fn/dom.js.js.js 。
$D()
:是仅当应用程序正在开发时才能启动通过函数的函数。它使用之前桥接的is_dev
变量。
$S()
:QuerySelector的缩写
$SA()
:querySelectorall的缩写
Page_loader类
首先;更多的助手功能;这些完成了大部分工作;他们获取并转换数据。
我们也导入了前面提到的帮助者。
/front/logic/classes/loader.js
import { D$ } from "../fn/dev.js";
import { S$, SA$ } from "../fn/dom.js";
/**
* @description get the sheet-attribute off of buttons
* @param {HTMLButtonElement} _btn
* @returns {string} - Sheet
*/
const get_sheet = (_btn) => {
return _btn.getAttribute("sheet") || "";
};
/**
* @description fetch sheet and return its data
* @param {string} _sheet
* @returns {response} - string
*/
async function find_sheet(_sheet) {
const path = `./sheets/${_sheet}.html`;
const F = await fetch(path, {
method: "GET",
})
.then((response) => {
// D$(console.log, response);
return response.text();
})
.then((data) => {
return data;
})
.catch((error) => {
D$(console.log, error);
return "";
});
return F;
}
/**
* @description convert string to html of header-main-footer
* @param {*} _html
* @returns {array} - object of header_data, main_data, footer_data
*/
const data_to_html = (_html) => {
var parser = new DOMParser();
var doc = parser.parseFromString(_html, "text/html");
const header_data = S$("header-content", doc)?.innerHTML.trim() || "";
const main_data = S$("main-content", doc)?.innerHTML.trim() || "";
const footer_data = S$("footer-content", doc)?.innerHTML.trim() || "";
return [header_data, main_data, footer_data];
};
和主类;它只能使用sheets
属性和<content-slot>
标签查询所有NAV-BUTTON,并将单击事件附加到那些Nav-Buttons。
您可以添加更多功能。例如,在启动时自动加载home.html表。或最后使用的表格。
以及一些导航功能,例如显示当前表是什么。
export class page_loader {
#header_slot;
#main_slot;
#footer_slot;
#all_nav_btns;
constructor() {
this.#get_targets();
this.#get_nav();
}
// query native elements
#get_targets() {
this.#header_slot = S$("#app-header content-slot");
this.#main_slot = S$("#app-content content-slot");
this.#footer_slot = S$("#app-footer content-slot");
}
#get_nav() {
this.#all_nav_btns = SA$("#feature-nav [sheet]");
}
/**
* Fetch given sheet and render the data in the app
* @param {string} _sheet - sheet of data to fetch
* @param {HTMLButtonElement} _btn - button to turn on in the nav
* @returns {void}
*/
async #render(_sheet, _btn) {
const data = await find_sheet(_sheet);
if (!data) return;
const [header_data, main_data, footer_data] = data_to_html(data);
this.#header_slot.innerHTML = header_data;
this.#main_slot.innerHTML = main_data;
this.#footer_slot.innerHTML = footer_data;
}
/**
* @description checks to see if the loader has succesfully retrieved all nav btns and the content slots
* @returns {boolean}
*/
is_ready() {
if (
this.#all_nav_btns &&
this.#header_slot &&
this.#main_slot &&
this.#footer_slot
)
return true;
return false;
}
/**
* @description function to activate click events on nav-btns
*/
activate() {
this.#all_nav_btns.forEach((btn) => {
btn.addEventListener("click", (e) => {
const sheet = get_sheet(btn);
this.#render(sheet, btn);
});
});
}
}
它有效,但是...
我在使用此类时注意到的是,当我在sheet.html中的<script>
标签中编写javascript时;它不会在index.html中触发;这并不意味着允许任何脚本渗透到这些文件是安全的。我的猜测是,当获取重试读取文件时而不是“粘贴”到我们的index.html。
但是,如果您想导入一些JS怎么办?出色地;我注意到自定义元素可以正确渲染(如果它们在我们的app.js文件中定义);因此,您可以使用自动加载JS代码的自定义元件。
注意:我不能真正谈论这种方法的安全性;我会说还不错,但是,如果这些HTML文件被损坏,那么班级将无法了解,不要介意手工。
结论:使用框架ð
系列结论
在这4篇文章中,我准备从电子和桌面应用程序开始制定第一步。我必须说,与Web开发相比,与Web开发相比,我很惊讶的是,至少在此示例中。我认为,如果我在哪里深入研究这个世界,那将需要更多的设置。
我发现当然可以与电子合作而没有框架(在意识到自己可以使用一个应用之前,我已经完全构建了我的应用程序);但这会有所改善。
我喜欢它与我习惯的网络开发有多近,并且使用它感觉很不错,但是我无法真正将其与其他App-Dev框架相比。
但是,应该提到(The Electron Saga 0)在我旅途开始时的错误错误。他们确实引起了一些困惑和担忧。
总的来说,围绕这个新环境嘲笑,远离潜伏在我肩膀上的项目很有趣。
说到这,我应该回到那些。我希望您能从这个系列中得到一些东西。
再见! ð