## 什么是electron
```
Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架,
是一个非常牛的跨平台的开发工具,
像我们用的vscode就是用electron开发的,electron 本质是一个浏览器,
但是里面内置了node的环境,所以可以操作本地文件。
```
- 生命周期:https://zhuanlan.zhihu.com/p/352668011
- 主进程和渲染进程:main主进程,rander渲染进程
```
主进程:适用前端技术作为app的gui,我们可以把它当做一个小型的chrom内核浏览器,负责创建和管理BrowserWindow实例以及各种应用程序事件。
它还可以执行诸如注册全局快捷方式,创建系统菜单和对话框,响应自动更新事件等操作。
应用程序的入口点将指向将在主进程中执行的JavaScript文件。
主进程以及所有node.js模块中都提供了一部分ElectronAPI(请参见下图)。
渲染过程负责运行应用程序的用户界面,换句话说,就是作为webContents实例的网页,每个页面使用自己的线程,这些线程就被称为渲染线程。
渲染进程中提供了所有DOM API,node.js API和ElectronAPI的子集(请参见下图),在一定程度上可以与操作系统进行交互。
```
## electron 安装和运行
```
默认我们都是有node环境,自行搜索,node安装。
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start
```
**打包**
```
npm install --save-dev electron-packager
npm run-script package
```
```
"package": "electron-packager . 'app' --platform=darwin --arch=x64 --icon=app.icns --out=./dist --asar --app-version=1.0.0 --ignore=\"(dist|src|docs|.gitignore|LICENSE|README.md|webpack.config*|node_modules)\"",
"packageDarwin": "electron-packager . '应用名称' --platform=darwin --arch=x64 --icon=app.icns --out=./dist --asar --app-version=1.0.0 --ignore=\"(dist|src|docs|.gitignore|LICENSE|README.md|webpack.config*|node_modules)\"",
"packageDarwin2": "electron-packager . '应用名称' --platform=darwin --arch=x64 --icon=app.icns --out=./dist --asar --app-version=1.0.0",
"packageWin": "electron-packager . '应用名称' --platform=win32 --arch=x64 --icon=app.ico --out=./dist --asar --app-version=1.0.0 --ignore=\"(dist|src|docs|.gitignore|LICENSE|README.md|webpack.config.js|node_modules)\"",
"packageWin2": "electron-packager . '应用名称' --platform=win32 --arch=x64 --icon=app.ico --out=./dist --asar --app-version=1.0.0",
"start": "electron ."
-----配置里面不能有汉字,要使用英语替代
```
## 部分electron案例
**如果需要使用node环境和electron部分api等需要在主进程mainjs里面配置**
```
webPreferences: {
nodeIntegration: true,
contextIsolation:false,
}
```
**1,文件拖拽**
```
为了让用户能够通过HTML5的file API直接操作本地文件,DOM的File接口提供了对本地文件的抽象。Electron在File接口中增加了一个path属性,它是文件在系统中的真实路径。
const fs = require("fs");
document.addEventListener('drop', (e) => {
e.preventDefault();//取消默认行为
e.stopPropagation();//阻止冒泡
console.log(1)
for (const f of e.dataTransfer.files) {
console.log('File(s) you dragged here: ', f,e)
fs.readFile(f.path,'utf-8',(err,data)=>{
if (!e) {
document.getElementById('text').innerHTML = data
}
})
}
});
document.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
console.log(2)
});
```
**2,自定义快捷键**
```
在主进程中配置
const {app, dialog, globalShortcut} = require('electron')
app.on('ready', () => {
globalShortcut.register('CommandOrControl+Alt+K', () => {
dialog.showMessageBox({
type: 'info',
message: '成功!',
detail: '你按下了一个全局注册的快捷键绑定.',
buttons: ['好的']
})
})
})
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
```
**3复制黏贴**
```
渲染进程
<body>
<a href="../index.html">返回</a>
<div id="copy-to">复制</div>
<input type="text" id="copy-to-input">
<div id="showCopy"></div>
<script>
const {clipboard} = require('electron')
const copyBtn = document.getElementById('copy-to')
const copyInput = document.getElementById('copy-to-input')
const showCopy = document.getElementById('showCopy')
copyBtn.addEventListener('click', () => {
clipboard.writeText(copyInput.value)
showCopy.innerHTML=copyInput.value
})
</script>
</body>
```
**4webview**
```
主进程里面配置
webPreferences: {
webviewTag:true,
}
渲染进程
<webview id="foo" src="https://www.baidu.com/"></webview>
如何操作webview
const wb = document.querySelector('#foo');
//开始加载事件监听
wb.addEventListener("did-start-loading", ()=> {
console.log("did-start-loading...");
})
//停止加载事件监听
wb.addEventListener("did-stop-loading", ()=> {
console.log("did-stop-loading...");
//注入css,视频生效,自己没生效
wb.insertCSS(`
body {
display: none!important;
}
`)
//注入js脚本
wb.executeJavaScript(`
setTimeout(()=>{
alert("粉丝数:",111);
}, 2000);
`)
//打开调试工具
wb.openDevTools();
})
```
**5shell对象**
```
主进程里面配置
webPreferences: {
enableRemoteModule:true
}
渲染进程
<body>
<a href="../index.html">返回</a>
<div id='href' hrefs="https://www.baidu.com/">shell打开外部链接</div>
<div id="openwidnows">openwidnows打开内部</div>
<script>
const { shell } = require('electron')
let dom = document.getElementById('href')
let srt = dom.getAttribute('hrefs')
console.log(11, srt)
dom.onclick = function (e) {
shell.openExternal(srt)
}
//在Electron10.x中,enableRemoteModule的默认值为false,也就是默认情况下是不支持使用remote模块的,因此使用remote模块的应用程序需要enableRemoteModule显式设置为true。
var BrowserWindow=require('electron').remote.BrowserWindow;
const path = require('path')
const item = document.getElementById('openwidnows')
item.onclick = function () {
let file = path.join(__dirname, './04.webview.html')
let win = new BrowserWindow({ width: 800, height: 600 })
// Load a remote URL
win.loadURL(file)
win.on('closed', () => {
win = null
})
}
</script>
</body>
```
**6window对象的操作**
```
父窗口打开子窗口,子窗口向父窗口发送信息
```
- 父窗口
```
<body>
<a href="../index.html">返回</a>
<h2>弹出子窗口</h2>
<button οnclick="startpop()">开启</button>
<button οnclick="closedpop()">关闭</button>
<script>
let win=""
function startpop() {
// win= window.open('https://www.baidu.com/', '_blank', 'top=500,left=200,frame=false,nodeIntegration=no')
win= window.open('./06.wchild.html','popup','top=300,left=200,')
}
function closedpop() {
win.close()
}
window.addEventListener('message',function (e) {
console.log(111,e)
})
</script>
</body>
```
- 子窗口
```
<body>
<a href="../index.html">返回</a>
<div>我是window打开的本地页面</div>
<button οnclick="sendmsg()">向父窗口发送信息</button>
<script>
function sendmsg() {
window.opener.postMessage('这是来自子窗口问候')
window.opener.postMessage({
type:1,
messageChannel:'这是来自子窗口问候'
})
}
</script>
</body>
```
**7主进程menu菜单menu-js渲染进程菜单**
```
1在页面右击出现菜单
2在任务栏出现菜单
```
**8渲染进程和主进程的通讯(同步和异步)**
- 使用ipc一异步方式在进程之间发送消息是首选方法,因为他会在完成时返回,而不会阻止同一进程中的其他操作,此实例将在渲染进程发送’ping‘到主进程,然后主进程返回’pong‘,渲染进程接受
```
渲染进程
const {ipcRenderer} = require('electron')
const asyncMsgBtn = document.getElementById('async-msg')
asyncMsgBtn.addEventListener('click', () => {
ipcRenderer.send('asynchronous-message', 'ping')
})
ipcRenderer.on('asynchronous-reply', (event, arg) => {
const message = `异步消息回复: ${arg}`
document.getElementById('async-reply').innerHTML = message
})
主进程
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
event.sender.send('asynchronous-reply', 'pong')
})
```
## 结合vue开发
- ①electron-vue文档----- https://simulatedgreg.gitbooks.io/electron-vue/content/cn/
- ②脚手架安装electron-vue
```
# 如果没有 vue-cli 的话需要全局安装
npm install -g vue-cli
# 然后使用 vue-cli 来安装 electron-vue 的模板
vue init simulatedgreg/electron-vue grpc-client-electron-vue
# 安装依赖
cd grpc-client-electron-vue
yarn # or npm install
# 进入开发模式
yarn run dev # or npm run dev
开发ok,打包有问题grpc-client-electron-vue项目,
```
- ③使用ui框架antd,vue开发一样,安装依赖,引入项目,vue文件使用
```
a. npm i --save ant-design-vue
b. 在项目src-renderer-main.js引入,
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.use(Antd);
```
- ④关闭eslint
```
注释掉如下的代码:
//{
// test: /\.(js)$/,
// enforce: 'pre',
// exclude: /node_modules/,
// use: {
// loader: 'eslint-loader',
// options: {
// formatter: require('eslint-friendly-formatter')
// }
// }
```
- ⑤跨域
```
文件src-main-index.js
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
//允许跨域
webPreferences:{
webSecurity:false
}
})
```
- 当 node 版本高于 12 的时候,会报错:
```
解决方法:打开.electron-vue 文件夹中的 webpack.web.config.js 和 .electron-vue/webpack.renderer.config.js,
在 HtmlWebpackPlugin,添加 templateParameters,如下所示:
templateParameters(compilation, assets, options) {
return {
compilation: compilation,
webpack: compilation.getStats().toJson(),
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: options
},
process,
};
},
```
## 最终版本
-[git地址](https://umbrella22.github.io/electron-vue-template-doc)
```
四,结合vue开发源码,可打包
开发使用vue devtools ,代码里面已经配置,首次运行时候需要下载vue-devtools ,但是安装有问题,造成原因是国内网问题,需要翻墙,打包成功以后就无须翻墙了。
import electronDevtoolsInstaller, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
function onAppReady () {
initWindow()
DisableButton.Disablef12()
if (process.env.NODE_ENV === 'development') {
electronDevtoolsInstaller(VUEJS_DEVTOOLS)
.then((name) => console.log(`installed: ${name}`))
.catch(err => console.log('Unable to install `vue-devtools`: \n', err))
}
}
```
## 学习资料中文文档
- [Electron 中文文档](http://www.niuguwen.cn/kaifashouce-cat-138.html)
- [Electron 官网](http://www.electronjs.org/)
- [electron入门到精通-项目实战](https://www.bilibili.com/video/BV16f4y1q7xz?t=796&p=19)