Electron知识点总结(未完)

Electron项目结构

your-app/
├── package.json
├── main.js
└── index.html

  • main.js:主线程,一个程序只有一个主进程
  • index.html:主界面的ui布局文件
  • package.json:程序的入口

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const electron = require('electron'); //引入electron模块
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

let mainWindow = null; //初始化一个主窗口的变量
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
heigth: 600,
webPreferences: { nodeIntegration: true }//集成node.js
});
require('./main/menu.js')//加载菜单
mainWindow.webContents.openDevTools()//打开调试窗口
mainWindow.loadFile('index.html');//加载布局文件

mainWindow.on('close', () => {
mainWindow = null;
})
})

nodeIntegration:仅在应用程序上执行一些不受信任的远程代码时,true才存在安全风险。 例如,假设应用程序打开了第三方网页。 这将带来安全风险,因为第三方网页将有权访问节点运行时,并且可以在用户的文件系统上运行某些恶意代码。 在这种情况下,将nodeIntegration设置为false是有意义的。 如果应用程序不显示任何远程内容,或仅显示受信任的内容,则将nodeIntegration:true设置为可以。

package.json

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "FirstProject",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HelloWorld</title>
</head>

<body>
Hello World
</body>

</html>

运行截图

fs模块读取本地文件

index.html文件的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HelloWorld</title>
</head>

<body>
<Button id="btn">显示</Button> //点击button在div中显示txt文本中的内容
<div id="content"></div>
<script src="render/render.js"></script>//引入渲染进程
</body>

</html>

新建一个渲染进程render.js

1
2
3
4
5
6
7
8
9
10
11
12
13
const fs = require('fs');//引入fs模块

window.onload = function() {
let button = this.document.getElementById('btn');
let content = this.document.getElementById('content');

//给button添加监听事件
button.onclick = function() {
fs.readFile('str.txt', (err, data) => {
content.innerText = data;
})
}
}

Remote模块

remote 模块为渲染进程(web页面)和主进程通信(IPC)提供了一种简单方法。

在Electron中, GUI 相关的模块 (如 dialogmenu 等) 仅在主进程中可用, 在渲染进程中不可用。 为了在渲染进程中使用它们, ipc 模块是向主进程发送进程间消息所必需的。 使用 remote 模块, 你可以调用 main 进程对象的方法, 而不必显式发送进程间消息, 类似于 Java 的 RMI 。例如:从渲染进程创建浏览器窗口

index.html文件

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">显示</button>
<script src="render/render.js"></script>
</body>
</html>

渲染进程内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
onst {BrowserWindow} = require('electron').remote //渲染进程的窗口
window.onload = function(){

let btn = document.getElementById('btn')
btn.onclick = function(){
let win = new BrowserWindow({
width: 400,
height: 300,
})

win.loadFile('yellow.html') //加载子页面的布局文件

win.on('close', ()=>{
win = null
})
}
}

require(‘electron’).remote就相当于主进程中的require(‘electron’)

菜单的创建和绑定

我们需要创建一个menu.js文件,用来编写菜单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const {Menu, BrowserWindow} = require('electron')
//创建菜单模板
let template = [
{
label:"文件",//选项名称
submenu:[
{
label:'新建文件',
accelerator: 'ctrl+n',//绑定快捷键
//添加监听事件
click: ()=>{
//添加动作
}
},
{label:'打开文件'},
{label:'首选项'}
]
},
{label:"查看"},
{label:"关于"},
{label:"帮助"}
]

let m = Menu.buildFromTemplate(template) //从模板建立菜单

Menu.setApplicationMenu(m)//设置为程序的菜单

main.js添加require('./main/menu.js'),加载菜单文件

右键菜单

index.html链接入渲染进程文件

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="render/render.js"></script>//渲染进程
</body>
</html>

render.js文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const {remote} = require('electron')

/**
* 菜单模板
*/
let rightTemplate = [
{
label: '粘贴',
accelerator: 'ctrl+alt+c',
},
{
label: '复制'
}
]

let m =remote.Menu.buildFromTemplate(rightTemplate)//建立菜单

window.addEventListener('contextmenu',(e)=>{
e.preventDefault()//阻止默认
m.popup({window:remote.getCurrentWindow()})//弹出右键菜单
})

在浏览器中打开链接

index.js文件

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<a href="https://litterboys.xyz" id="blog">Litterboys Blog</a>
<script src="render/render.js"></script>
</body>
</html>

渲染进程中内容

1
2
3
4
5
6
7
8
let {shell} = require('electron') //shell模块提供与桌面集成相关的功能。
let blog = document.getElementById('blog') //获取a标签对象
//添加监听事件
blog.onclick = function(e){
e.preventDefault()//阻止默认事件
let href = this.getAttribute('href')//获取链接
shell.openExternal(href)//在额外的浏览器窗口打开
}

嵌入网页

在主进程中嵌入网页

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

let mainWindow = null; //主窗口

app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
heigth: 600,
webPreferences: { nodeIntegration: true }
});

mainWindow.loadFile('index.html');//加载布局文件


//BrowserView
let BrowserView = electron.BrowserView
let view = new BrowserView()
mainWindow.setBrowserView(view)
view.setBounds({x:0, y:120,width:800,height:400})
view.webContents.loadURL('https://litterboys.xyz')


//open window
mainWindow.on('close', () => {
mainWindow = null;
})
})

BrowserView 被用来让 BrowserWindow 嵌入更多的 web 内容。 它就像一个子窗口,除了它的位置是相对于父窗口。 这意味着可以替代webview标签.w

window.open打开子窗口与传递消息

window.open将为url创建一个新的BrowserWindow实例,默认情况下, 新创建的 BrowserWindow 将继承父窗口的选项。若要重写继承的选项, 可以在 features 字符串中设置它们。

1
2
3
4
5
//渲染进程
let button = document.getElementById('open')//父窗口的打开按钮,在index.html文件中
button.onclick = ()=>{
window.open('./popup_page.html','_blank','width=400,height=300')
}

子窗口可以通过window.opener.postMessage()来向父窗口传递消息

子窗口的html文件内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子窗口</title>
</head>
<body>
<h2>我是子窗口</h2>
<button id="send">传递消息</button>
</body>

<script>
let popbtn = document.getElementById('send')
popbtn.onclick = (e)=>{
window.opener.postMessage('来自子窗口的消息')
}
</script>
</html>

然后在父窗口的渲染进程中可以通过以下代码来捕获到消息

1
2
3
4
window.addEventListener('message',(msg)=>{
let text = document.getElementById('text')//index.html中的div控件
text.innerHTML = JSON.stringify(msg.data)//显示消息
})

显示效果如下

选择与保存文件对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HelloWorld</title>
</head>

<body>
<button id="open">选择文件</button>
<button id="save">保存文件</button>
<img id="pic" style="width: 100%"></img>
<script src="render/render.js"></script>
</body>

</html>

渲染进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const {dialog} = require('electron').remote; //获取渲染进程的dialog对象

let open = document.getElementById('open')//获取按钮对象
let pic = document.getElementById('pic')
//为打开文件按钮添加监听事件
open.onclick = ()=>{
dialog.showOpenDialog({
title:'选择文件', //对话框标题
defaultPath: 'C:\\Users\\litterboy\\Pictures\\VIVOX9-手机照片', //默认起始路劲
//文件选择器
filters:[
{
name:'img',
extensions:['jpg','png']
}
],
buttonLabel:'打开' //自定义打开按钮名字
}).then(result=>{ //获取到结果对象
if(result.filePaths[0] != undefined){
pic.setAttribute('src',result.filePaths[0]) //显示图片
}
}).catch(err=>{
console.log(err)
})
}


const fs = require('fs')
let save = document.getElementById('save') //获取‘保存文件’按钮对象
save.onclick = ()=>{
dialog.showSaveDialog({
title: '保存文件' //对话框标题
}).then(result=>{
fs.writeFileSync(result.filePath,'Hello World') //保存文件的内容
}).catch(err=>{
// console.log(err)
})
}

程序运行截图

弹出对话框

渲染进程

1
2
3
4
5
6
7
8
9
10
11
let message = document.getElementById('dialog') //获取按钮对象
message.onclick = ()=>{
dialog.showMessageBox({
type: 'warning', //类型
title: '警告', //标题
message: '程序终止', //信息
buttons:['终止','确定'] //按钮的选项
}).then(result=>{ //返回值,返回buttons的数组下表,比如选择“终止”为0,“确定”为1
console.log(result)
})
}

网络监测

render.js

1
2
3
4
5
6
7
window.addEventListener('online',()=>{    //很简单的监听事件
alert("网络连接成功")
})

window.addEventListener('offline',()=>{
alert('网络断开连接')
})
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信