在本系列的上一篇文章中,我们谈到了如何去搭建一个简单的hello wordl桌面应用,那么这篇文章,来谈谈几个我们在桌面应用中常用的功能
对于一个桌面应用来说,很多信息都会保存在本地的文件,在我们使用该应用时,读取本地对应的文件,去显示不同的内容
这类似于我们在使用web端时,需要去从服务端读取我们想要的配置文件等信息,将信息以各种形式渲染到页面上。对于桌面应用来说,设置一般都是保存在本地的,我们可以将桌面应用读取本地的文件,和web端发起请求的行为对比,其实原理都是一样的。
而这里的读写,我们直接用到了fs模块,其实这里只要熟悉fs模块的话,是可以直接看代码了,基本没什么差别,但是这里我们借着说文件的读写,来说说怎么在Electron中的渲染进程(也就是在各个页面)使用node.js
这里写一个小demo,读取配置文件中的内容,渲染到应用页面上,同时使用写操作修改配置文件
首先在根目录创建一个全局配置文件global.json,同时新建文件夹render用来存放渲染文件
修改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 .
即可打开桌面应用
这里我们在打开时会根据global.json的内容进行渲染,当我们提交修改后会修改本地的global.json文件,所以当我们下次打开的时候,会使用我们上一次修改的配置,这也符合我们在桌面应用中,配置相应的内容保存后会在下次打开时显示我们新配置的内容
在之前的笔记中,已经提到了如何新建一个桌面应用,但那是在主线程中创建的,而有时候,我们需要在渲染进程中新建一个应用窗口,这种场景也不少见,往往我们会通过点击一个按钮来创建一个新窗口,或者像编辑器一样,我们有时会同时打开两个应用窗口
在electron中,GUI相关的模块仅在主线程中可用,渲染进程中不可用,这其中就包括了BrowserWindow,而我们是使用BrowserWindow来创建新窗口的,有什么方法可以让我们在渲染进程中使用它吗,答案当然是有的
electron通过remote模块为渲染进程和主进程之间的通信提供了一种简便的方法
我们写一个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
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内容,实际开发我们可以从代码里面去获取它
而实际上,除了本地文件可以以这种方式打开外,我们也可以通过另一个方法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,来防止内存的泄露。