Electron
npx
作用:
- 调用项目安装的模块
- npx 想要解决的主要问题,就是调用项目内部安装的模块。比如,项目内部安装了测试工具 Mocha。($ npm install -D mocha)
- 一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面, 如果想在命令行下调用,必须像这样(// 项目的根目录下执行 $ node-modules/.bin/mocha --version)。
- npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。(npx mocha --version)
- 避免全局安装模块
- 除了调用项目内部模块,npx 还能避免全局安装的模块。比如,create-react-app这个模块是全局安装,npx 可以运行它,而且不进行全局安装。($ npx create-react-app my-react-app)
- 上面代码运行时,npx 将create-react-app下载到一个临时目录,使用以后再删除。所以,以后再次执行上面的命令,会重新下载create-react-app。
原理:
- npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
- 由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。(// 等同于 ls $ npx ls)
electron应用
hello world
- 主进程
// main.js
const electron = requrie('electron');
const app = electron.app; // 控制应用程序的事件生命周期
const BrowserWindow = electron.BrowserWindow; // 创建和控制浏览器窗口
let mainWindow = null; // 主窗口
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 900,
height: 900,
webPreferences: {
nodeIntegration: true // 配置渲染进程可以使用nodejs
}
})
mainWindow.loadFile('./index.html') // 加载渲染文件
mainWindow.on('close', () => {
mainWindow = null; // 窗口关闭时销毁主窗口
})
})
- 渲染进程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
</head>
<body>
<button id="btn">展示</button>
<div id="show"></div>
<script src="./render/index.js"></script>
</body>
</html>
- 渲染进程js交互
// 以读取文件为例
var fs = require('fs');
window.onload = function() {
const btn = document.querySelector('#btn');
const show = document.querySelector('#show')
btn.addEventListener('click', function() {
fs.readFile('readMe.text', function(err, data) {
show.innerHTML = data.toString()
})
})
}
- 运行
electron .
remote模块
作用: 在渲染进程中使用主进程模块
使用:
// 首先需要在主进程中的webPreferences中配置 enableRemoteModule: true,
mainWindow = new BrowserWindow({
width: '100%',
height: '100%',
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
},
});
// 渲染进程 index.js
const BrowserWindow = require('electron').remote.BrowserWindow // 在渲染进程中使用主进程中的BrowserWindow
window.onload = function() {
const open = document.querySelector('#open') // 在页面中打开新的窗口
open.onclick = function() {
let newWin = new BrowserWindow({
width: 900,
height: 900,
});
newWin.loadFile('../index.html');
newWin.on('close', () => {
newWin = null;
});
};
}
ELectron中菜单的创建和绑定事件
// 构建menu菜单文件
const {
Menu,
BrowserWindow
} = require('electron')
const template = [{
label: '菜单一',
submenu: [{
label: '子菜单一',
accelerator: 'ctrl + n', // 设置快捷键
click: () => {
let newWin = new BrowserWindow({
width: 800,
height: 800,
webPreference: {
nodeIntegration: true
}
})
}
},
{
label: '子菜单二'
}
]
},
{
label: '菜单二',
submenu: [{
label: '子菜单一'
},
{
label: '子菜单二'
}
]
}
]
const m = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(m)
// 最后再把这个文件引入主线程main.js中就可以啦
打开调试窗口
// 在主进程中使用主窗口的对象
mainWindow.webContents.openDevTools({
mode: 'detach'
}) //不写mode:detach默认是合并的
右键菜单
// 制作模板
const rightTemplate = [{
label: '复制',
accelerator: 'ctrl+c'
},
{
label: '粘贴',
accelerator: 'ctrl+v'
}
]
const m = remote.Menu.buildFromTemplate(rightTemplate)
// 在渲染进程中绑定右键事件
window.addEventListener('click', function(e) {
e.preventDefault()
m.popup({
// 弹出窗口
window: remote.getCurrentWindow()
})
})
Electron中通过链接打开浏览器(shell模块)
const remote = require('electron').remote
const {
BrowserWindow,
shell
} = remote
const aHref = document.querySelector('#baidu')
aHref.onclick = function(e) {
e.preventDefault()
const href = aHref.href
shell.openExternal(href)
}
Electron中嵌入网页和打开子窗口
- electron中嵌入网页(BrowserView)
// 主进程中 main.js
const BrowserView = electron.BrowserView
const view = new BrowserView()
mainWindow.setBrowserView(view) //主进程添加BrowserView
view.setBounds({
//设置大小位置
x: 0,
y: 100,
width: 800,
height: 800
})
view.webContents.loadURL('https://www.baidu.com') // BrowserView内容
- 打开子窗口(window.open(url))
子窗口向父窗口通信
方法:window.opener.postMessage (注意:window.opene()打开的是子窗口,new BrowserWindow()打开的是新的窗口,与原先窗口没有直接关系)
// 父窗口
window.open('other.html') // 绑定事件跳转子窗口
window.addEventListener('message', function(data) {
// 监听子窗口传来的消息
alert(data.data)
})
// 子窗口中使用window.opener.postMessage()
// 绑定事件发送消息
btn.onclick = function() {
window.opener.postMessage('发送消息给父窗口')
}
选择文件对话框(dialog)
const {
dialog
} = require('electron').remote
// 事件绑定
btn.onclick = () => {
dialog.showOpenDialog({
defaultPath: '/', // 默认为项目根路径
title: '设置标题',
filters: [{
name: 'image',
extensions: ['jpg', 'png'], // 过滤文件
}],
buttonLabel: '打开这个文件' // 自定义打开按钮文案
}).then(data => {
console.log(data.filePaths[0]) // 图片路径
}).catch(err => {
console.log(err)
})
}
保存文件对话框(dialog)
const fs = require('fs')
// 不会保存空文件
dialog.showSaveDialog({
title:'保存文件'
}).then( data => {
console.log(data.filePath) // 保存文件的路径
fs.writeFileSync(data.filePath,'哈哈哈哈')
}).catch( err => {
console.log(err)
})
消息对话框(dialog)
btn.onclick = () => {
dialog.showMessageBox({
type:'warning' // none、info、error、question,
title:'设置标题',
message:'设置消息内容',
buttons:['是','否'] // 设置按钮交互
}).then( result => {
console.log(result) // 交互的结果以数组的索引显示,result.response 0,1,2....
}).catch( err => {
console.log(err)
})
}
断网提醒功能
- 利用h5的事件监听
window.addEventListener('online',function(){
alert('网络连接成功')
})
window.addEventListener('offline',function(){
alert('断网了')
})
底部消息通知
btn.onclick = () => {
const option = {
title:'消息标题',
body:'消息内容~~~~'
}
new window.Notification(option.title,option)
}
注册全局快捷键
// 主线程中(main.js)
const electron = require('electron')
const globalShortcut = electron.globalShortcut
app.on('ready',function(){
// 一定要在 ready之后才能注册快捷键
const isRegistered = globalShortcut.isRegistered('ctrl+q') // 判断是否被注册
if(!isRegistered){
globalShortcut.register('ctrl+q',function(){
// what to do
mainWindow.loadURL('https://www.jd.com')
})
}
})
app.on('will-quit',function(){
globalShortcut.unregister('ctrl+e') // 单一注销
globalShortcut.unregisterAll() // 全部注销
})
剪切板功能
const {
clipboard, dialog } = require('electron').remote
clipboard.writeText(code.innerHTML)
dialog.showMessageBox({
message: '复制成功'
})