Electron
# 安装
在命令行执行以下命令快速安装
```javascript
# Clone the repository
$ git clone https://github.com/electron/electron-quick-start
# Go into the repository
$ cd electron-quick-start
# Install dependencies
$ npm install
# Run the app
$ npm start
```
<img width="100%" src="https://user-images.githubusercontent.com/17243165/28075783-173e52f6-668f-11e7-998a-415aa5c3978c.png" />

执行完后打开应用的效果图
![image](https://user-images.githubusercontent.com/17243165/28075832-44b951fe-668f-11e7-9c18-4cba5f37d939.png)

# 文件目录

- .gitignore(git上传提交时候过滤文件)
- index.html(electron应用页面主入口，前端)
- main.js(控制electron应用窗口的生命周期和参数设置，窗口通信设置)
- package.json(记录electron应用的依赖，和启动命令)
- renderer.js(配合`index.html`使用的了逻辑文件，控制前端的逻辑，可以调用`NodeJS`所有的内置`API`和第三方模块)

# 调试

自动打开`dev-tool`工具，方便调试
```js
mainWindow.webContents.openDevTools()
```
# renderer

`renderer.js`是可以在这里调用`node`内置模块和`npm`的第三方模块，也可以直接操作`DOM`写页面逻辑
```js
require('./renderer.js')
```
我们可以在这里编写前端逻辑，然后用`node`模块去调计算机系统的功能，比如创建服务器，执行系统命令
```js
const express = require('express');
const fs = require('fs');
// 读取系统文件
fs.readFile('/Users/eno/Documents/Wscats/day1.md', (err,data) => {
        console.log(data.toString())
}
const app = express();
app.get('/', (req, res) => res.send('Hello World!'));
const exec = require('child_process').exec;
// Vue
methods: {
    test() {
        app.listen(3000, () => console.log('Example app listening on port 3000!')); // 启动服务器
        let cmdStr = 'ls'; // ls命令，读取当前electron开发目录的文件列表
        exec(cmdStr, function (err, stdout, stderr) { // 执行系统命令
            if (err) {
                console.log('error:' + stderr);
                return;
            } else {
                console.log(stdout);
            }
        });
},
```
新版新增了个`preload.js`，使`renderer.js`使用不了Node原生API，需要在主进程里面加入这句配置
```js
function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true, // <===
      preload: path.join(__dirname, 'preload.js')
    }
  })
}
```
当然如果没有这一句也可以这样，在`preload.js`暴露原生`Node`的模块接口，然后在`renderer.js`中就可以使用原生模块了
```js
// preload.js
const fs = require('fs')
window.fs = fs
```

# 引入jQuery

安装jQuery模块，并在执行脚本中引入
```javascript
const jquery = require('jquery');
loginedWindow.loadURL("https://github.com/Wscats");
loginedWindow.webContents.executeJavaScript(`
	window.$ = require("jquery");
	console.log($);
`);
```

## 页面通信

通过electron的ipcRenderer的send方法，可以实现在页面的脚本中触发nodejs中定义好的逻辑
```javascript
require("electron").ipcRenderer.send("logined");
ipcMain.on("logined", function(event) {
	        //electron.app.quit();
		setTimeout(function() {
		mainWindow.hide()
	}, 5000)
});
```
比如在页面中你运行了一个脚本如下
```js
//窗口的执行的脚本
mainWindow.webContents.executeJavaScript(`
	require("electron").ipcRenderer.send("answer","Wscats");
`);
//后端执行的逻辑
ipcMain.on("answer", function (event, data) {
        //执行的逻辑
});
```

## 脚本中的数据传递

通过字符串模板拼接，把脚本的数据添加到模板中
```javascript
var account = {
	username: "wscats",
	email: "wscats@163.com",
	password: "wscats"
}
mainWindow.webContents.executeJavaScript(`
	$("[name='Account']").val("wscats");
	$("[name='PassWord']").val("wscats");
	//require("electron").ipcRenderer.send("logined");
	$("[type='submit']").trigger("click",function(){})
`)
```

## <webview> 标签

可以使用webview标签嵌套网页
```html
<webview id="foo src="https://www.github.com/"></webview>
```
必须要在`dom-ready`才能调用webview的API方法，可以通过`executeJavaScript`和`insertCSS`往该webview上注入JS脚本和CSS样式
```js
window.onload = function () {
    var webview = document.getElementById("foo");
    webview.addEventListener("dom-ready", function () {
        webview.openDevTools();
        console.log(webview.getURL())
        webview.executeJavaScript(`
            console.log(document.getElementById("js-pjax-loader-bar"))
        `)
        webview.insertCSS(`
            #js-flash-container{background-color: green}
        `)
    });
}
```
当用户或page尝试开始导航时触发.它能在`window.location`变化或者用户点击连接的时候触发，这个事件在以 APIS 编程方式开始导航时不会触发，例如`<webview>.loadURL`和`<webview>.back`，在页面内部导航跳转也将不回触发这个事件，例如点击锚链接或更新`window.location.hash`使用`did-navigate-in-page`来实现页内跳转事件，并且使用`event.preventDefault()`并不会起什么用
```js
webview.addEventListener('will-navigate', function (e) {
    console.log("重定向")
});
```
参考[Electron DOM <webview> 标签](https://www.w3cschool.cn/electronmanual/9xri1qlc.html)

# 打包

我们可以使用`electron-packager`来打包，下面是`package.json`文件
```js
"scripts": {
  "start": "electron .",
  "dev": "electron . --debug",
  "test": "mocha && standard",
  "package": "npm-run-all package:*",
  "package:mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --out=out --icon=assets/app-icon/mac/app.icns --osx-sign.identity='Developer ID Application: GitHub' --extend-info=assets/mac/info.plist",
  "package:win": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=out --icon=assets/app-icon/win/app.ico",
  "package:linux": "electron-packager . --overwrite --platform=linux --arch=x64 --out=out"
}
```
建议用`cnpm`代替`npm`，速度会比较快，还有打包的素材`icons`，`Win`系统的图标必须是128*128的素材，如果在`Mac`下打包`Win`的安装包，必须要安装`wine`环境

- [可以参考electron-lemon的源代码进行打包](https://github.com/Wscats/node-tutorial/tree/master/WechatAutoReply/electron-lemon)
```
cnpm run package //打包所有版本
cnpm run package:win // 打包win版本
```
<img width="1342" alt="2019-01-17 12 52 39" src="https://user-images.githubusercontent.com/17243165/51296379-fa475800-1a56-11e9-8801-dc47539fc4fa.png">

- [打包的静态资源文件可以参考这里的assets文件夹](https://github.com/electron/electron-api-demos)
- [electron打包：electron-packager及electron-builder两种方式实现（for Windows）](https://segmentfault.com/a/1190000013924153)
- [Electron 桌面应用打包（npm run build）简述(windows + mac)](https://segmentfault.com/a/1190000012899824)

# 图标制作

可以参考[想制作和修改mac下icns图标的朋友进](https://bbs.feng.com/read-htm-tid-7176712.html)

- [icns tool工具下载](https://github.com/Wscats/node-tutorial/tree/master/WechatAutoReply/icns-tool)

Xcode 已经不再集成 Icon Composer，不用 Icon Composer 一样制作 Icon ，要想再用，只能去

> Xcode->Open Develop Tool->More Develop Tools->下载 Additional_Tools_for_Xcode_10.1.dmg

里面会包含Icon Composer

# electron-vue

electron-vue 是一个结合 vue-cli 与 electron 的项目，主要避免了使用 vue 手动建立起 electron 应用程序，很方便。

我们需要做的仅仅是像平常初始化一个`vue-cli`项目一样
```bash
npm install -g vue-cli 
vue init simulatedgreg/electron-vue my-project
```

就可以拥有一个 vue-loader 的 webpack、electron-packager 或是 electron-builder，以及一些最常用的插件，如vue-router、vuex 等等的脚手架


# 参考文档

[electron打包客户端与网页程序交互](https://segmentfault.com/q/1010000006249534)
[electron实战开发详细流程](http://www.myk3.com/arc-8856.html)
[官方快速入门文档](https://electron.atom.io/docs/tutorial/quick-start/)