建立一个空的文件夹,并建立入口 main.js
文件,index.html
内容文件,html
安装electron
前端
npm init -y:初始化配置文件 package.jsonnode
npm i electronweb
main.js 文件shell
引入模块,建立应用npm
建立窗口json
加载内容windows
打开调试工具(可选)api
关闭窗口及应用监听数组
执行文件
直接执行:electron main.js
默认执行:electron .
package.json 添加执行脚本: "start": "electorn main.js", 执行:npm run start
执行上述命令报错解决:先可尝试全局安装,在执行命令,如若仍然报错,可能须要配置脚本执行权限
windows下运行*.ps1
脚本(powershell的脚本)的时候,须要设置执行权限,PowerShell默认的执行策略就是Restricted
,禁止任何脚本的执行。
首先管理员身份运行 windows powershell ,输入Get-ExecutionPolicy
,用于得到当前的执行策略。
Set-ExecutionPolicy
命令设置/更改执行策略,选择RemoteSigned
这个执行策略,这个策略既安全又能够执行本地编写的脚本
// main.js 引入模块 // app模块:控制应用的生命周期 // BrowserWindow模块: 建立浏览器窗口 const { app ,BrowserWindow} = require('electron'); // path模块: node 的内置模块,用于拼接路径 const path = require('path'); // 1.初始化应用以后,会触发监听ready 事件 app.on('ready',ny_createWindow) let win; // 建立窗口 function ny_createWindow(){ // 1.1建立窗口 win = new BrowserWindow({ width:330, height:355, resizable:false, // 是否可改变宽高,默认true movable:false, // 是否可拖拽,默认true webPreferences: { nodeIntegration: true, // 是否集成 Nodejs enableRemoteModule: true, // 是否容许渲染进程 调用主进程模块 } // 1.为了在渲染进程中使用require(),还须要启用 nodeIntegration 。 // 2.从v9版本开始,remote除非将 enableRemoteModule 设置为true,不然不容许在渲染进程中使用。 }); // 1.2 加载内容 // win.loadURL('http://www.baidu.com') // 远程 // __dirname: 当前js文件所在的文件夹路径,绝对路径 // win.loadURL(path.join(__dirname, './index.html')) // 本地 相对路径 // mac 系统:须要拼接 file 协议 // path.join('file://',__dirname,'./index.html') // 1.3 调试工具 win.webContents.openDevTools(); // webContents: 控制和渲染页面的 // 1.4 关闭窗口, 关闭窗口前想作的事 win.on('close',function(){ win = null; // 关闭窗口 app.quit(); // 关闭应用 })
建立menu.js
,引入模板,建立菜单模板
构建菜单(实例化一个菜单对象)
设置菜单对象到应用中
用到的方法:buildFromTemplate
, setApplicationMenu
选项:
main.js中引用: require('./menu');
// menu.js 引入模板 const { Menu } = require('electron') // 1.设置一个模板 let template = [ { label:'文件', submenu:[ { label:'新建文件', accelerator:'ctrl+N', click:function(){ console.log('new file') } }, { type:'separator' }, { label:'新建窗口', accelerator:(function(){ if(process.platform =='darwin'){ //mac 基于darwin return 'alt+command+M' }else{ //win return 'alt+ctrl+M' } })(), click:function(){ console.log('new window') } }, { type:'separator' }, { label:'自动保存', accelerator:'ctrl+S', type:'checkbox', checked:true, click:function(){ console.log('saved') } }, ] }, { label:'编辑' }, ] // 2. 构建菜单(实例化一个菜单对象) const menu = Menu.buildFromTemplate(template); //3. 设置菜单对象到应用中 Menu.setApplicationMenu(menu);
在Electron中,入口是一个js文件,运行这个入口文件的进程称做主进程。
(一般会是package.json
里的main脚本,通常是main.js)
在主进程使用BrowserWindow
模块能够建立并管理web页面,也就是应用的GUI(图形界面)
const { BrowserWindow } = require('electron'); const path = require('path'); // 主进程建立web页面 let win = new BrowserWindow({...}); // 加载本地文件 // win.loadURL(path.join('file://',__dirname, './index.html')) // mac win.loadURL(path.join(__dirname, './index.html'))
在主进程建立的每个web页面也都运行着本身的进程,页面引入的js文件就属于渲染进程。
渲染进程各自管理本身的页面,能够想象是浏览器的一个个的tab。
electron核心能够分红2个部分,主进程
和渲染进程
。主进程链接着操做系统和渲染进程,能够看作页面和计算机沟通的桥梁。渲染进程就是咱们所熟悉前端环境了。只是载体改变了,从浏览器变成了window。传统的web环境咱们是不能对用户的系统进行操做的。而electron至关于node环境,能够在项目里使用全部的node api 。
简单理解:
给web项目套上一个node环境的壳。
建立渲染进程对应render.js
文件
渲染进程引入BrowserWindow
模块,须要借助于remote
模块,
enableRemoteModule
,容许渲染进程 调用主进程模块并在index.html
中引入render.js
,两种引入方法及区别
<!-- 1.引入render.js --> <script src="./render-process/render.js"></script> <!-- 2.electron 基于node --> <script> require('./render-process/render.js'); </script> <-- 区别: src: 是全局变量 require: 引入的文件的最外层的变量,不是全局变量,注:为了在渲染进程中使用require(),还需在主进程窗口配置中启用 nodeIntegration 。 //main.js win = new BrowserWindow({ width:330, height:355, resizable:false, // 是否可改变宽高,默认true movable:false, // 是否可拖拽,默认true webPreferences: { nodeIntegration: true, // 是否集成 Nodejs enableRemoteModule: true, // 是否容许渲染进程 调用主进程模块 } }) 使用: 1.元素绑定onclick事件 ==== src引入 2.require ==== 给元素绑定一个ID ,在render.js获取元素并绑定事件 -->
在electron下,主进程与渲染进程相互通讯要经过ipc(Inter-Process Communication),进程间通信模块
来完成,
主进程与渲染进程调用的ipc模块是不同的:
主进程调用ipcMain
渲染进程调用ipcRenderer
ipcRenderer
模块:渲染进程引入,用于发送事件给主进程,和监听主进程返回的回复事件
const { ipcRenderer } = require('electron')
;
发送事件:ipcRenderer.send('事件名称',传递的数据)
;
监听事件:ipcRenderer.on('监听事件名称',接收的数据)
;
ipcMain
模块:主进程引入,用于接收渲染进程发送的事件并进行回复
const { ipcMain } = require('electron')
;
监听事件:ipcMain.on('监听事件名称',接收的数据)
;
index.html:
<h1>Hello Electron!</h1> <button onclick="ny_click()">click me</button> <!-- 引入render.js 渲染进程--> <script src="./render-process/render.js"></script>
render.js:
function ny_click(){ console.log('Render:','Echoyya') ipcRenderer.send('myName','Echoyya'); }
main.js:
ipcMain.on('myName',function(event,msg){ console.log('Main:',msg); })
运行结果:主进程输出结果会打印在终端,而渲染进程输出结果会打印在调试工具中
了解了 渲染进程 -> 主进程
后,反之就很好理解和掌握了,大同小异,简单总结一下:
main.js 发送指令 两种方式:
ipcMain.on('myName',function(event,msg){ // 1. 经过event //event.sender.send('msg-b','程序媛'); // 2. 经过webContents (推荐) win.webContents.send('msg-b','程序媛'); })
render.js 渲染进程接收指定
ipcRenderer.on('msg-b',function (event, msg) { console.log('Render:',msg) });
运行结果:
思路:渲染进程 -> 主进程 -> 渲染进程
a.js: ipcRenderer.send('dataToMain','
渲染进程 -> 主进程 -> 渲染进程')
main.js:
ipcMain.on('dataToMain',function(event,data){ win.webContents.send('dataToRender',data); })
b.js:
ipcRenderer.on('dataToRender', function (event, data) { console.log(data) })
能够很简单的使用H5的api来完成,如localStorage,sessionStorage,但今天要说的是另外一种
在主进程中将一个对象储存为全局变量,而后经过remote
模块操做
a.js
, b.js
,并在index.html
中引入index.html:
<button id="btn1">改变数据</button> <button id="btn2">获取数据</button> <script> require('./render-process/a.js'); require('./render-process/b.js'); </script>
main.js:
// 全局变量 global.shareObject = { name:'上海' }
a.js:
const remote = require('electron').remote; let btn1 = document.getElementById('btn1'); btn1.onclick = function(){ remote.getGlobal('shareObject').name = '北京'; console.log('has changed'); }
b.js:
const remote = require('electron').remote; let btn2 = document.getElementById('btn2'); btn2.onclick = function(){ let msg = remote.getGlobal('shareObject').name console.log(msg) }
首先dialog模块是主进程可以使用模块
调用语法:dialog.showMessageBox({ ... })
,版本升级后不支持原来的回调方法,改成返回promise
对象
经常使用配置对象参数:
const { dialog ,nativeImage} = require('electron'); const path = require('path'); // 1.信息对话框 dialog.showMessageBox({ title:'舒适提示', message:'XXXXX XXXXX XXXXX XXXXX XXXXX', buttons:['Yes','No'], icon:nativeImage.createFromPath(path.join(__dirname,'../src/img/icon1.png')) }).then(function(index){ if(index.response == 0){ // 点击了Yes按钮 console.log('I want you !'); }else{ // 点击了No按钮 console.log('no no no'); } }); // 2.错误提示框 dialog.showErrorBox('1213','访问错误')
打包必要元素及格式输入:electron-packager <应用目录> <应用名称> <打包平台> --out=<输出目录> <架构> <应用版本> <忽略文件> <图标> --overwrite
执行上述命令,可在输出目录中,打包成功一个exe 可执行文件,此命令区分mac及win,设备缘由,此处仅演示win系统打包,mac系统的同窗,需自行查找相关资料!!!
package.json:
"scripts": { "start": "electorn main.js", "pack":"electron-packager ./ test --platform=win32 --out=./dist --arch=x64 --app-version=1.0.0 --ignore=node_modules --icon=./src/img/hrbb.ico --overwrite " },