基于Node.js的GUI框架
- NW.JS (Node-Webkit)
- Electron
1.使用HTML、CSS、JavaScript来构建UI、处理与用户的交互、同时不约而同的使用了开源浏览器Chromium。基于这个浏览器做了一系列的软件开发,比如:Vscode、Atome、网易云音乐等。
2.使用Node.js来访问浏览器之外的内容。比如文件系统、文件、网络等,相当于是浏览器与Node.js的结合。
安装使用
- 使用
npm init -y
来初始化项目。 - 安装electron
npm i electron
- 在
package.json
中设置项目入口文件index.js
{
"name": "node-gui",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"electron": "^9.0.2"
}
}
- 新建
index.js
文件
项目入口文件时Electron第一个加载的文件,是整个项目的入口。 - 使用electron的运行命令编译文件
/node_modules/.bin/electron index.js
这里可以在package.json
中配置启动程序的脚本。就不用每次都输入这么长的命令。
{
"name": "node-gui",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"gui":"./node_modules/.bin/electron ."
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"electron": "^9.0.2"
}
}
这里就可以使用npm run gui
启动程序,
Demo开发
1.在Electron中用来展示界面的web页面都运行在一个独立的,属于自己的渲染进程中。
2.在Electron中,被直接运行的脚本(package.json中的main脚本)被称为主进程。
3.在Electron中用来展示界面的web页面都运行在一个独立的、属于他自己的渲染进程中。
4.主进程管理所有web也买你和他们对应的渲染进程。
5.一个应用程序有且仅仅有一个主进程。
6.在Electron中,Electron同时为主进程和渲染进程暴露了Node.js的所有接口,也就是说,我们可以在Electron的住进程与渲染进程中使用Node.js的API。
- app对象
该对象提供了一系列的时间用来控制整个应用程序的生命周期,从打开到关闭,如:
ready、window-all-closed、quit…
同时也提供了一些方法来管理应用程序的状态与行为,如:
quit()、relaunch()、hide()、show()…
index.js
:
const {app} = require('electron')
app.on('ready',()=>{
console.log('ok');
setTimeout(()=>{
app.exit()
},2000)
})
- BrowserWindow类
创建和控制浏览器窗口,每一个BrowserWindow对象的实例都是一个独立的渲染进程,同时改对象也提供了各种用于操控的API,包括:事件、属性、方法。
index.js
:
const {
app,
BrowserWindow
} = require('electron')
app.on('ready', () => {
//创建窗口,配置相关信息
let bw1 = new BrowserWindow({
width: 600,
height: 600,
resizable: false,
alwaysOnTop: true,
title: 'test1'
})
let bw2 = new BrowserWindow({
width: 600,
height: 600,
resizable: false,
alwaysOnTop: true,
title: 'test2',
parent: bw1, //设置当前窗口时bw1的子窗口
modal: true //设置为模态窗口
})
//类似浏览器的window对象
// bw1.webContents
bw1.webContents.openDevTools()
//加载指定页面到窗口中,支持绝对路径
bw1.loadFile('./resource/index1.html') //这里只当resource中的index.html
//此方法支持远程文件,支持http协议,也支持file协议
bw2.loadURL('https://www.baidu.com')
})
- Menu类
创建新菜单–new Menu()
index.js
:
const { app, BrowserWindow, Menu, MenuItem} = require('electron')
app.on('ready', () => {
//创建窗口,配置相关信息
let bw1 = new BrowserWindow()
//创建菜单项
let m1 = new Menu()
//创建菜单项
let mItem1 = new MenuItem({
type: 'normal',
label: '文件'
})
let mItem2 = new MenuItem({
type: 'submenu',
label: '编辑',
submenu: [{
type: 'normal',
label: '打开'
},
{
type: 'normal',
label: '退出',
click(){//给菜单添加事件
app.quit()
}
}
]
})
//把菜单项添加到指定的菜单对象中
m1.append(mItem1)
m1.append(mItem2)
//指定菜单显示
//具体的位置、那个窗口、右键-上下文
Menu.setApplicationMenu(m1) //把菜单添加到长头的最顶部
})
- 数据共享
通过浏览器API实现:remote对象、ipcRenderer对象、渲染进程之间可以用storage来传地数据
index.js
:
const { app, BrowserWindow,ipcMain} = require('electron')
let username = 'yang'
//给全局对象绑定数据
global.username = username
//监听ipcRenderer发送的数据
app.on('ready', () => {
let bw1 = new BrowserWindow({
webPreferences: {
nodeIntegration: true, // 解决index.html require报错问题
}
})
bw1.webContents.openDevTools()
bw1.loadFile('./resource/index1.html')
ipcMain.on('getData',(e,...data)=>{
console.log(data);
// e.sender => 通过这对象再返回消息给渲染进程
e.sender.send('sendData', 1000)
})
//主进程主动发送消息到渲染进程
bw1.webContents.send('hello','hello Yang')
})
index1.html
:
<body>
<h1>index1</h1>
<button>点击</button>
<script>
const remote = require('electron').remote;
const ipcRenderer = require('electron').ipcRenderer;
//该对象有一个global方法,可以获取主进程中的数据
console.log(remote.getGlobal('username'));
const btn = document.querySelectorAll('button')
btn[0].onclick = function(){
ipcRenderer.send('getData','yang')
}
//监听主进程的方法
ipcRenderer.on('sendData',(e,...data)=>{
console.log(data);
})
//监听主进程主动发送数据的方法
ipcRenderer.on('hello',(e,...data)=>{
console.log(data);
})
</script>
</body>
- 效果:
打包
- 使用electron-builder进行打包:官网
- 在
package.json
中进行配置:配置方法 - 安装:
npm i electron-builder
- 打包命令:
./node_modules/.bin/electron-builder -w
package.json
:
{
"name": "node-gui",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"gui": "./node_modules/.bin/electron .",
"build": ".\\node_modules\\.bin\\electron-builder -w"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^9.0.2",
"electron-builder": "^22.7.0"
},
"build": {
"appId": "testId",
"productName": "yang",
"copyright": "Copyright © 2020 authorName",
"directories": {
"output": "./dist"
}
},
"win": {
"target": [
"nsis"
]
},
"nsis": {
"onClick": false,
"allowToChangeInstallationDirectory": true,
"license": "./resource/content.txt"
}
}
注意: 可能打包的时候对报错
只需要将package.json
中 dependencies的{electron,electron-builder}放入devDependencies中。