Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建

在本系列的上一篇文章中,我们谈到了如何去搭建一个简单的hello wordl桌面应用,那么这篇文章,来谈谈几个我们在桌面应用中常用的功能

文件的读写


对于一个桌面应用来说,很多信息都会保存在本地的文件,在我们使用该应用时,读取本地对应的文件,去显示不同的内容

这类似于我们在使用web端时,需要去从服务端读取我们想要的配置文件等信息,将信息以各种形式渲染到页面上。对于桌面应用来说,设置一般都是保存在本地的,我们可以将桌面应用读取本地的文件,和web端发起请求的行为对比,其实原理都是一样的。

而这里的读写,我们直接用到了fs模块,其实这里只要熟悉fs模块的话,是可以直接看代码了,基本没什么差别,但是这里我们借着说文件的读写,来说说怎么在Electron中的渲染进程(也就是在各个页面)使用node.js

这里写一个小demo,读取配置文件中的内容,渲染到应用页面上,同时使用写操作修改配置文件

首先在根目录创建一个全局配置文件global.json,同时新建文件夹render用来存放渲染文件
Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建_第1张图片
修改index.html,引入相应的js文件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <p>hello <span id="name">xxxspan>p>
    <button id="refresh">更新button>
    <p>
        <label>名字:label>
        <input type="text" id="nameInput">
    p>
    <p>
        <label>颜色:label>
        <input type="text" id="colorInput">
    p>
    <button id="submit">提交修改button>
    <script src="./render/index.js">script>
body>
html>

在render文件夹下的index.js,写入对应的读写操作

const fs = require('fs')
window.addEventListener('load',()=>{
    renderData()
    window.document.querySelector('#refresh').addEventListener('click',()=>{
        renderData()
    })
    
    window.document.querySelector('#submit').addEventListener('click',()=>{
        submitData()
    })
})

// 渲染数据
function renderData(){
    fs.readFile('global.json',(err,data)=>{
        let configData = JSON.parse(data)
        window.document.querySelector('#name').innerHTML = configData.name
        window.document.querySelector('#nameInput').value = configData.name
        window.document.querySelector('body').style.color = configData.color
        window.document.querySelector('#colorInput').value = configData.color
    })
}

// 提交修改
function submitData(){
    let data = JSON.parse(fs.readFileSync('global.json'))
    data.name = window.document.querySelector('#nameInput').value
    data.color = window.document.querySelector('#colorInput').value
    fs.writeFile('global.json',JSON.stringify(data),()=>{
        alert('修改完成')
        renderData()
    })
}

最后,在根目录的global.json文件中,添加相应的配置

{
    "name":"前端小白",
    "color":"black"
}

命令行electron .即可打开桌面应用
Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建_第2张图片
这里我们在打开时会根据global.json的内容进行渲染,当我们提交修改后会修改本地的global.json文件,所以当我们下次打开的时候,会使用我们上一次修改的配置,这也符合我们在桌面应用中,配置相应的内容保存后会在下次打开时显示我们新配置的内容

新窗口的创建

在之前的笔记中,已经提到了如何新建一个桌面应用,但那是在主线程中创建的,而有时候,我们需要在渲染进程中新建一个应用窗口,这种场景也不少见,往往我们会通过点击一个按钮来创建一个新窗口,或者像编辑器一样,我们有时会同时打开两个应用窗口

在electron中,GUI相关的模块仅在主线程中可用,渲染进程中不可用,这其中就包括了BrowserWindow,而我们是使用BrowserWindow来创建新窗口的,有什么方法可以让我们在渲染进程中使用它吗,答案当然是有的

electron通过remote模块为渲染进程和主进程之间的通信提供了一种简便的方法

关于主进程和渲染进程各自的模块,可见文档
Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建_第3张图片

我们写一个demo来实践一下
修改index.html为


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <button id="openBtn">打开新窗口button>
    <script src="./render/index.js">script>
body>
html>

在根目录下创建index2.html
Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建_第4张图片
index2.html中随便写入内容


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>index2title>
head>
<body>
    <p>我是新打开的页面p>
body>
html>

最后修改render中的js文件,给按钮添加点击事件

const { BrowserWindow } = require('electron').remote

window.addEventListener('load',()=>{
    window.document.querySelector('#openBtn').addEventListener('click',()=>{
        let newWindow = new BrowserWindow({
            width:600,
            height:600,
            webPreferences: {
                nodeIntegration: true
            }
        })
        newWindow.loadFile('index2.html')
        newWindow.on('closed',()=>{
            newWindow = null
        })
    })
})

如果我们希望让新页面可以接收我们本页面传递的一些内容,可以在loadFile的第二个参数传入相应的内容,这里以search为示例,详情可见文档

window.document.querySelector('#openBtn').addEventListener('click',()=>{
    let newWindow = new BrowserWindow({
        width:600,
        height:600,
        webPreferences: {
            nodeIntegration: true
        }
    })
    newWindow.loadFile('index2.html',{
        search:'a=1&b=2'
    })
    newWindow.on('closed',()=>{
        newWindow = null
    })
})

这里我直接在新页面的开发者工具里面去打印search内容,实际开发我们可以从代码里面去获取它
Electron开发笔记----前端小白开发桌面应用之路(二)文件的读写和新窗口的创建_第5张图片
而实际上,除了本地文件可以以这种方式打开外,我们也可以通过另一个方法loadURL,来打开一个网址

window.document.querySelector('#openBtn').addEventListener('click',()=>{
    let newWindow = new BrowserWindow({
        width:600,
        height:600,
        webPreferences: {
            nodeIntegration: true
        }
    })
    // newWindow.loadFile('index2.html',{
    //     search:'a=1&b=2'
    // })
    newWindow.loadURL('https://www.baidu.com')
    newWindow.on('closed',()=>{
        newWindow = null
    })
})

这里修改之后,会发现点击打开了一个桌面应用里的百度页面

远程对象

实际上,这里我们使用到的BrowserWindow是一个远程对象,在文档中有提到:

remote 模块返回的每个对象 (包括函数) 表示主进程中的一个对象 (我们称它为远程对象或远程函数)。 当调用远程对象的方法时, 调用远程函数, 或者使用远程构造函数 (函数) 创建新对象时, 实际上是在发送同步进程消息。

所以这里的new BrowserWindow实际上在渲染过程中并没有创建一个BrowserWindow对象,而是在主进程中创建了一个BrowserWindow对象,并在渲染进程中返回该远程对象

既然是在主进程中创建的对象,那么就涉及到了,这个对象什么时候会被释放,对Electron来说,只要确保渲染进程中的远程对象一直存在,主进程中的相应对象就不会被释放。而当渲染进程中的对象被垃圾回收,主进程的相应对象就会被解除引用。这也就是为什么,我们一定要注意当一个窗口关闭时,要将对象赋值的变量置为null,来防止内存的泄露。

你可能感兴趣的:(Electron,JavaScript)