使用 Electron 创建 GeeksforGeeks 包装应用程序
Electron是一个开源且独立于平台的框架,用于使用 Chromium 引擎和 Node.js 的强大功能创建本地桌面应用程序。
我们将使用 Electron 创建一个简单的应用程序,它充当 GeeksforGeeks 网站的包装器。它包含快速导航到网站重要部分的功能,在需要时单独打开“在线 IDE”并保存以后可以离线阅读的文章。
它利用了 Electron 框架的各种功能,包括浏览器窗口、本地菜单、文件处理和打包应用程序以进行分发。
先决条件:
- 运行 Electron 应用程序需要Node.js 运行时。这包括像npm这样的工具来帮助构建和安装所需的包。在 Windows 上安装 Node.js。
- 了解HTML、CSS 和 JavaScript
- Electron和Node.js的入门知识
初始化一个新的 Node 项目:
- 导航到您希望创建项目的位置。打开命令提示符并使用以下命令初始化新项目:
npm init
- 按照命令提示符窗口中的要求填写项目的详细信息。这将创建一个package.json文件,该文件指示将用于运行应用程序的所有库。
- 使用以下 npm 命令安装 Electron 包:
npm install electron
- 打开package.json文件并将“scripts”部分更改为以下内容:
"scripts": { "start": "electron ." }
这使得通过 npm 实用程序运行我们的应用程序变得很容易。
创建 Electron 基本结构:我们首先创建应用程序的基本结构。 index.js (或package.json中配置的相应文件)是 Electron 可执行文件尝试启动应用程序的入口点。我们将使用以下代码在index.js文件中定义应用程序结构:
- 程序:
const { app, BrowserWindow } = require('electron') // Global variable that holds the app window let win function createWindow() { // Creating the browser window win = new BrowserWindow({ width: 960, height: 540, }) // Load a redirecting url from // login to the feed win.loadURL( 'https://auth.geeksforgeeks.org/?to=https://auth.geeksforgeeks.org/profile.php') win.on('closed', () => { win = null }) // Prevent from spawning new windows win.webContents.on('new-window', (event, url) => { event.preventDefault() win.loadURL(url) }) } // Executing the createWindow function // when the app is ready app.on('ready', createWindow)
- 该应用程序可以使用以下命令运行:
npm start
- 输出:
解释:
- 我们已经定义了一个带有窗口尺寸的BrowserWindow ,并使用loadURL()方法加载了网站的登录页面。 BrowserWindow 就像嵌入在我们的应用程序中的浏览器,可用于浏览网页。
- 每当运行此应用程序时,它都会创建 BrowserWindow 的一个实例并将指定的 URL 加载到窗口中。
创建菜单: Electron 应用程序具有创建菜单项的功能,这些菜单项将本机显示在应用程序的菜单栏中。这些可以链接到单击它们时将发生的操作。
菜单最初是从一个模板创建的,该模板定义了每个菜单和子菜单的显示方式以及它们的作用。我们的菜单有 6 个部分:
- 文件:它可以选择保存当前页面并退出应用程序。
- 站点:它具有登录和注销网站的选项。
- 学习:它可以选择已撰写文章的网站的各个部分。
- 练习题:它可以选择在单独的窗口中打开在线IDE,也可以根据难度直接进入问题。
- 贡献:它具有与文章对网站的贡献相对应的各种选项。
- 已保存的文章:它允许访问以前已保存的所有文章。
所有 URL 均直接来自 GeekforGeeks 网站。 “保存的页面”部分留空,以便以后更新。通过创建 BrowserWindow 的新实例并在其中加载 URL,将为在线 IDE 创建一个单独的窗口。
最终模板菜单代码如下:
let menu_template = [
{
label: 'File',
submenu: [
{
label: 'Save Page Offline',
click() {
savePageOffline()
}
},
{ type: 'separator' },
{
label: 'Exit',
click() {
app.quit()
}
}
]
},
{
label: 'Site',
submenu: [
{
label: 'Login',
click() {
win.loadURL(
"https://auth.geeksforgeeks.org")
}
},
{
label: 'Logout',
click() {
win.loadURL(
"https://auth.geeksforgeeks.org/logout.php")
}
},
]
},
{
label: 'Learn',
submenu: [
{
label: 'Quiz Corner',
click() {
win.loadURL(
"https://www.geeksforgeeks.org/quiz-corner-gq/")
}
},
{
label: 'Last Minute Notes',
click() {
win.loadURL(
"https://www.geeksforgeeks.org/lmns-gq/")
}
},
{
label: 'Interview Experiences',
click() {
win.loadURL(
"https://www.geeksforgeeks.org/company-interview-corner/")
}
},
{
label: 'Must-Do Questions',
click() {
win.loadURL(
"https://www.geeksforgeeks.org/must-do-coding-questions-for-companies-like-amazon-microsoft-adobe/")
}
}
]
},
{
label: 'Practice Questions',
submenu: [
{
label: 'Online IDE',
click() {
// Creating new browser window for IDE
ide_win = new BrowserWindow({
width: 800,
height: 450,
})
ide_win.loadURL(
"https://ide.geeksforgeeks.org")
// Delete this window when closed
ide_win.on('closed', () => {
ide_win = null
})
}
},
{ type: 'separator' },
{
label: 'Easy Questions',
click() {
win.loadURL(
"https://practice.geeksforgeeks.org/explore/?difficulty[]=0&page=1")
}
},
{
label: 'Medium Questions',
click() {
win.loadURL(
"https://practice.geeksforgeeks.org/explore/?difficulty[]=1&page=1")
}
},
{
label: 'Hard Questions',
click() {
win.loadURL(
"https://practice.geeksforgeeks.org/explore/?difficulty[]=2&page=1")
}
},
{ type: 'separator' },
{
label: 'Latest Questions',
click() {
win.loadURL(
"https://practice.geeksforgeeks.org/recent.php")
}
}
]
},
{
label: 'Contribute',
submenu: [
{
label: 'Write New Article',
click() {
win.loadURL(
"https://contribute.geeksforgeeks.org/wp-admin/post-new.php")
}
},
{
label: 'Pick Suggested Article',
click() {
win.loadURL(
"https://contribute.geeksforgeeks.org/request-article/request-article.php#pickArticleDiv")
}
},
{
label: 'Write Interview Experience',
click() {
win.loadURL(
"https://contribute.geeksforgeeks.org/wp-admin/post-new.php?interview_experience")
}
}
]
},
{
id: 'saved',
label: 'Saved Articles',
submenu: []
}
]
解释:
- 我们将首先导入Menu和MenuItem命名空间。这些包含我们将要使用的方法的定义。
- label属性定义了每个项目的文本。 submenu属性指定单击 MenuItem 时将打开的子菜单项数组。
- 在每个标签之后,可以定义单击子菜单时将发生的操作。例如,我们将使用loadURL()方法加载网站的其他部分。每当用户单击子菜单时,它将执行此方法并加载网站的新部分。
- 定义了一个变量,它保存将从模板构建的菜单。 Menu命名空间具有buildFromTemplate()和setApplicationMenu()方法,可以在我们的应用程序中使用创建的菜单。
// Build the template and use the menu const menu = Menu.buildFromTemplate(menu_template) Menu.setApplicationMenu(menu)
添加保存页面的功能:我们现在将添加将页面保存到磁盘的功能,以便以后即使没有互联网连接也可以访问它。我们将首先定义我们的文章将被存储的位置。我们可以获取当前工作目录并为保存的页面创建一个文件夹。
const savedFolder = __dirname + '\\saved\\'
三个函数共同作用来保存和检索文章:
appendItemToMenu(filename)函数:
- 该函数将给定的页面标题添加到“保存的页面”子菜单中,并将其链接起来,以便在用户单击它们时加载页面。
- 使用getApplicationMenu()方法检索当前活动的菜单。
- 然后它使用append()方法添加一个新的 MenuItem。此 MenuItem 构造函数被赋予将显示为标签的文件名以及单击它时将发生的功能。
- 它会自动更新当前菜单,最新的页面可以立即使用。
- 代码:
function appendItemToMenu(filename) { curr_menu = Menu.getApplicationMenu() .getMenuItemById("saved").submenu curr_menu.append( new MenuItem({ label: path.basename(filename, '.html'), click() { console.log('Saved page opened') win.loadFile(savedFolder + path.basename(filename)) } })) }
savePageOffline()函数:
- 此函数将整个页面连同所有图像和样式表一起保存到磁盘。
- 文件名是使用getTitle()方法确定的,该方法返回当前页面的标题。
- contents.savePage()方法将获取当前网页并将其保存到具有上述标题的给定位置。
- 它还调用上面的appendItemToMenu()来更新菜单。
- 代码:
function savePageOffline() { pageTitle = win.getTitle() console.log("Saving:", pageTitle) win.webContents.savePage(savedFolder + pageTitle + '.html', 'HTMLComplete').then(() => { appendItemToMenu(pageTitle + '.html'); console.log('Page was saved successfully.') }).catch(err => { console.log(err) }) }
getSavedArticles()函数:
- 此函数检索给定文件夹中的所有文件,然后将它们添加到菜单中。
- 它使用readdirSync()方法返回“已保存”文件目录中存在的所有文件名。
- 检查文件名,以便只考虑扩展名为“.html”的文件名。
- 然后将它们传递给appendItemToMenu()函数,以便为每个保存的项目更新菜单。
- 代码:
function getSavedArticles() { fs.readdirSync(savedFolder).forEach(file => { if (path.extname(file) == '.html') { appendItemToMenu(file) } }); }
savePageOffline()函数是从“文件”菜单中的“离线保存页面”调用的。在创建 BrowserWindow 期间调用getSavedArticles()函数,以便之前的页面立即可用。每当保存新页面时都会调用appendItemToMenu()函数。这允许无缝保存和检索可以离线阅读的文章。
打包应用程序:由于 Electron 是一个独立于平台的框架,应用程序可以使用单个代码库在所有主要平台上运行。 Electron 社区已经创建了一个包,它为各种支持的平台捆绑了一个完成的应用程序,并使其准备好分发。
npm install electron-packager -g
electron-packager
--platform=
--arch= [optional flags...]
electron-packager . geeksforgeeks-desktop
进一步阅读:我们已经介绍了一个非常基本的应用程序,它展示了 Electron 的一些特性。该框架具有更多功能,可以集成在一起以构建更复杂的应用程序。建议通过以下链接进一步阅读:
- 官方电子文档
- 使用 Electron 构建的应用程序集合:电子应用程序
- 此应用程序的参考代码:geeksforgeeks-desktop