一.认识
定位

Electron is a framework for creating native applications with web technologies like JavaScript, HTML, and CSS.

实现

Electron = Node + Chromium + V8

这些只是Electron的依赖项,跨平台最关键的自然是适配层,由供node调用的C++模块来完成平台适配,提供系统级的平台接口

适用场景

桌面环境可能很难抹平差异,Electron的大多数API都是分平台的,例如quick start里的:

// Quit when all windows are closed.app.on('window-all-closed', function () {  // On OS X it is common for applications and their menu bar  // to stay active until the user quits explicitly with Cmd + Q  if (process.platform !== 'darwin') {    app.quit()  }})

如果想用Electron实现完美的跨平台一致体验,还要费不少功夫,甚至某些方面不可能做到一致(可能需要自己做一些C++模块来完成适配),就API体验来看,比ionic移动端跨平台更费劲,平台差异太多

但如果只是想“用JS写个Mac/Win工具,说不定还能跨平台”的话,即不考虑平台差异的话,Electron还算不错

二.开发环境
quick start
官方提供了quick-start,算是基本的试玩环境:

# Clone this repositorygit clone https://github.com/electron/electron-quick-start# Go into the repositorycd electron-quick-start# Install dependenciesnpm install# Run the app

npm start
在npm install可能遇到ETIMEDOUT,因为electron包非常大(120M):

node install.js.../node_modules/electron/install.js:48  throw err  ^Error: connect ETIMEDOUT 52.216.66.16:443    at Object.exports._errnoException (util.js:1034:11)    at exports._exceptionWithHostPort (util.js:1057:20)    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1096:14)

建议换用taobao镜像下载:

# 删除还没下载完成的rm -rf node_modules/electron# 指定taobao镜像ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ npm install electron

一切正常的话,能跑出来一个hello world窗口,看看API文档,体验一些系统原生API,比如系统托盘,桌面通知等等,试玩结束

如果打算开始搞的话,强烈不建议从quick start开始,因为还缺很多东西:

模块化方案

构建方案(开发-打包-发布)

组件库(UI库)

路由管理

持久化方案

那么可能还需要react、webpack、antd、react-router、xxx-storage等等一大堆东西,手动去做的话,只webpack构建方案就得小半天,所以,我们需要更强大的模版项目

boilerplate
对于react全家桶,这里推荐两份项目模版:

electron-react-boilerplate:yarn管理依赖,webpack构建

ReactReduxReact RouterWebpackReact Transform HMR

electron-react-redux-boilerplate:npm管理依赖,npm scripts构建

React RouterRedux ThunkRedux ActionsRedux Local StorageElectron PackagerElectron DevTools InstallerElectron MochaBrowsersync

webpack配置构建可扩展性更好一些,但实际使用发现electron-react-boilerplate构建配置相当复杂,本地没能跑起来,尝试解决无果后放弃了,改用electron-react-redux-boilerplate

两个模版都没有提供UI组件库,引入antd后发现npm scripts构建脚本很难解决自动引入css的问题(webpack可以添loader解决),暂时先拿cp顶着,后续考虑切换到webpack:

"private:style": "cp -f node_modules/antd/dist/antd.css build/antd.css; cp -rf app/css build/css"

P.S.在安装依赖时,也会遇到electron下载超时的问题,同样,环境变量指向taobao镜像:

ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ yarn

三.常见问题
1.让窗口紧贴托盘图标正下方
有现成模块,相当好用:

menubar

先获取托盘图标的位置,再根据窗口大小计算居中

2.系统托盘图标尺寸

For OS X, create icons:icon.png (for best results aim 16x16px)icon@2x.png (32x32px)For Windows, create single icon:icon.icoICO format will work better than classic PNG. If you want PNG, make it 32x32px.

摘自:Proper tray icon

Mac顶部菜单栏高度是22px,可以用22px或者16px的png格式图标

P.S.gif格式图片不可以用做图标

3.Mac系统通知中文乱码
HTML需要通过meta设置charset:

<meta charset="utf-8">

否则HTML里引入的外部JS资源里的字面量中文串,会出现乱码

4.持久化存储
建议使用electron-store

用JSON文件来存,放在应用安装目录里,API不太科学:

// set()只能存基本值store.set('unicorn', 'ma');console.log(store.get('unicorn'));//=> 'ma'// 存对象路径不方便store.set('foo.bar', true);console.log(store.get('foo'));//=> {bar: true}// store只能整个替换所有数据store.store = data

不很影响使用,读写都是同步的,存简单的用户配置比较合适。大量数据的话,可能存在性能问题

P.S.更多Electron数据存储方式请查看How to store user data in Electron

5.IPC
Electron里有两个进程,Main和Renderer,前者负责管理一切,并与平台交互,后者提供浏览器环境,渲染页面

进程间通信支持程度比较好,有同步和异步两种方式,通过事件消息来通信

异步通信(event.sender.send()):

// In main process.const {ipcMain} = require('electron')ipcMain.on('asynchronous-message', (event, arg) => {  console.log(arg)  // prints "ping"  event.sender.send('asynchronous-reply', 'pong')})// In renderer process (web page).const {ipcRenderer} = require('electron')ipcRenderer.on('asynchronous-reply', (event, arg) => {  console.log(arg) // prints "pong"})ipcRenderer.send('asynchronous-message', 'ping')

同步通信(event.returnValue):

// In main process.const {ipcMain} = require('electron')ipcMain.on('synchronous-message', (event, arg) => {  console.log(arg)  // prints "ping"  event.returnValue = 'pong'})// In renderer process (web page).const {ipcRenderer} = require('electron')console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

P.S.如果renderer发来的参数是undefined,直接传入系统接口,可能会遇到错误:

ERROR:v8_value_converter.cc(374)] Unexpected v8 value type encountered.

传递给系统接口的参数,应该严格校验,避免此类问题

6.开机自启
有现成模块:node-auto-launch

npm install --save auto-launch

P.S.Mac下确实添了一条启动项,但没有勾选,可能需要制定应用路径,待深入了解

写在最后
实际上,对系统级API的依赖比想象的少太多了,学习成本大多来自前端生态(React全家桶),完全合心意的组件库是不存在的

东西呢,还不成样子,下周继续

更多相关文章

  1. 超好用的ai文章生成器 智媒ai伪原创平台
  2. React17 系统精讲 结合TS打造旅游电商平台
  3. jquery easyui window或者dialog没有关闭图标是怎么回事
  4. 推荐web 前端代码的编辑分享平台——RunJS
  5. 如何更改Gmaps.js在Google地图中使用的图标?
  6. 【HTML&CSS】【7】网址栏左侧出现的图标Icon
  7. “/图标。ico " vs
  8. 图标旋转但返回上一个位置
  9. jQuery更改活动类图标的状态

随机推荐

  1. PacketReader 如何实现smack数据监听机制
  2. 第一个Android程序
  3. android中Appwidget的使用
  4. 在谷歌中映射V2…fragment.getMap()返回n
  5. 不同Android版本设备正确获取屏幕分辨率
  6. Android开发——联系人中几种常见的mimet
  7. android surfaceview里onTouchEvent 画图
  8. 绑定服务后台播放音频的简单示例
  9. 常用命令(Linux、Android、adb)
  10. 新浪微博开放平台开发-android客户端(1)