转载

使用 Electron 开发一款理财计算器

Electron 是一个跨平台应用框架,原本为 Atom 设计,后来单独分离了出来。它提供了一些与原生系统交互的 API ,可以方便快速使用 HTML、JavaScript、CSS 等 Web 技术开发跨平台应用。

最近基于 Electron 开发了一个简单的 理财计算器 。发布了 1.0 版本之后,总结一下这段时间的开发经历。哦对了,价格是随便定的,主要是熟悉下流程,大家千万别买。

这篇文章只包含个人开发小结,不包括各种框架工具的基础使用,如有需要请自行 Google 。

过程

理财计算器的功能很简单,目前只做了股票的保本卖出价的计算。

使用 Electron 开发一款理财计算器

输入买入价、买入数量等信息,算上各种手续费之后,输出保本卖出的价格。

看起来很简单的功能,大概却做了5天,主要在开发环境配置上卡了挺久。

基础项目

一开始需要做的是搭建整个项目的基础框架,主要包含以下几个方面:

  • electron :跨平台框架,主要是封装 Web 应用,并且打包发布。
  • webpack :模块加载打包工具,可以通过各种 loader 加载不同资源。
  • eslint :JS 代码静态检测工具,可以方便的统一代码的风格。
  • babel :可以将 ES6 代码转为 ES5 代码的语法编译器。
  • vue :前端框架,数据驱动的组件化开发,配上 vue-loader 之后十分好用。

上面这一套东西要搞一下还是比较费时间的,好在网上有各种现成的模板,货比三家之后最后选用了 electron-boilerplate-vue ,搭建好后文件目录如下:

. ├── .babelrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── README.md ├── app │   ├── ... │   ├── main.html │   ├── main.js │   └── package.json ├── build │   ├── ... │   ├── webpack.base.conf.js │   ├── webpack.dev-background.conf.js │   ├── webpack.dev-server.conf.js │   └── webpack.pro-build.conf.js ├── config.js ├── package.json └── test 

前端页面

接下来就是前端页面部分。一直想试试 Material Design 风格,刚好这次是个不错的机会,于是就开始找找有没有 MD 方面的前端库。

先是想看看有没有类似于 Ant Design 这样的成套 vue 组件库,于是找到了 material-ui ,可惜是 React 版本的。找找了 vue 版本的似乎只有 vue-mdl 和 vue-material 这两个不太成气候的库,仔细想想本身它们都依赖于其他前端库和 vue ,万一更新不及时岂不是很坑爹。于是弃了这个想法。

后来就是去找类似于 semantic-ui 和 Foundation 这样纯粹的前端库,找到 materializecss 这个库,页面简洁大方,破儿费(Perfect)啊!

然后,就是为期两天的填坑之旅。

是的,一共5天的开发时间,调教这个前端库花了2天,而且坑爹的是,最后还没用上。主要问题在于它的 JS 代码是基于 jQuery 的,而很多插件又是在 $(document).ready 里加载的,对 SPA 非常不友好,因为 document ready 的时候我的 dom 们还没 ready 。再加上我对 Webpack 又不是很熟悉,导致点击事件不响应,不知道是 webpack 打包的问题还是 vue-loader 加载顺序的问题还是 babel-loader 编译的问题还是它自己库的问题还是 jquery 引入的问题。

总之就是,一套系统过于庞大,虽然脚手架让我避开了大量的体力劳动,但是同时也引入了很多我不熟悉的未知因素。于是就刚好花两天时间,仔细学习了项目中用到的各种技术和工具。熟悉了之后才发现我以前多虑了,问题肯定出在源码上。然后就找到了问题的原因。

最后决定放弃 materializecss 这个库,然后去试了试 Google 家的 Material Design Lite 。

万万没想到,5分钟解决战斗。

引入 CSS 的方法和 materializecss 类似,都是在 SCSS 里 import 它的原文件:

/* IMPORT VARIABLES */ @import 'material-design-lite/src/_variables.scss'; /* OVERRIDE VARIABLES */ $layout-screen-size-threshold: 0px; /* IMPORT MDL */ @import 'material-design-lite/src/material-design-lite.scss'; 

引入 JS 文件的方法也很简单,和其他库一样 import 就行:

import 'material-design-lite' 

不过和 materializecss 不同的是,文档里在 《 Use MDL on dynamic websites 》 写清楚了动态更新页面后的更新方法:

// upgrade element componentHandler.upgradeElement(button) // upgrade dom componentHandler.upgradeDom() 

于是在 vue 的项目里,只要这么写就可以了:

<template>  .. </template>  <script type="text/babel">   export default {  ready: () => {  componentHandler.upgradeDom()  },  components: {  ...  },  } </script>  <style lang="scss" rel="stylesheet/scss">  </style> 

谷歌爸爸!受我一拜!

业务功能

接下来就是业务部分,计算器嘛还是挺简单的,感觉最有趣的部分是实时更新计算结果,这个功能通过 vue 这种数据绑定框架来实现真是太合适了。

核心代码是这样的,先用 v-for 组装表单控件:

<div> <div class="mdl-tabs mdl-js-tabs">  <div class="mdl-tabs__tab-bar">  <a v-on:click.prevent="clickTab(0)">沪市 A 股</a>  <a v-on:click.prevent="clickTab(1)">沪市 B 股</a>  <a v-on:click.prevent="clickTab(2)">深市 A 股</a>  <a v-on:click.prevent="clickTab(3)">深市 B 股</a>  </div>  <div>  <div v-for="item of currentTabItem">  <div>  <input type="text" id="{{ item.id }}" v-model="item.model"/>  <label for="{{ item.id }}">{{ item.label }}</label>  <span>{{ item.suffix }}</span>  </div>  </div>  <div id="result-panel" class="mdl-color-text--primary">  {{ result }}  </div>  </div> </div> </div> 

然后在 JS 里绑定数据:

export default{  ready: function (){  componentHandler.upgradeDom()  },  methods: {  clickTab: function (index){  this.currentTab = index  this.$nextTick(() => {  componentHandler.upgradeDom()  })  },  },  data: function (){  return {  currentTab: 0,  items: items,  }  },  computed: {  result: function (){  ...  return `${part1}${part2}`  },  currentTabItem: function (){  return items[this.currentTab]  },  }, } 

这样一旦输入的数字发生改变, model 就会改变,就会触发 result 改变,从而刷新 dom 上的显示结果。

其他

其他杂七杂八的东西比较多,拎一些踩过的坑记录一下。

打包

Electron 虽然提供了简单快捷的跨平台开发方案,但是并没有简单快捷的跨平台打包方案。从 《 Electron application packaging 》 来看,打包过程比较繁琐,反正我是划了5次触摸板才滚到了底部。

所幸的是, electron-packager 帮我们解决了这个问题,这个工具已经包含在了前面的了 electron-boilerplate-vue 里,现在打包只需以下命令即可:

"package": "node build/package.js", "package:osx": "node build/package.js --platform=darwin", "package:mas": "node build/package.js --platform=mas", "package:win": "node build/package.js --platform=win32", "package:linux": "node build/package.js --platform=linux", "release": "npm run build && npm run package", 

签名也很容易,只要加上 osx-sign 的选项即可:

if (packagerConfig.platform === 'mas') {  Object.assign(packagerConfig, {  'app-bundle-id': appManifest.bundleId,  'osx-sign': true,  }) } 

打包之后的结果是 .app 文件,如果需要上传到 Mac App Store 可以用 electron-osx-flat 将其转化成 .pkg 文件,然后通过 Xcode 里的 Application Loader 上传。

然而,并没那么省心。。。打包之后提交审核,审核人员说你这应用打开白屏了。我自己打开一看还真是。。。感觉是 osx-sign 导致的问题,于是就不打 mas 的包了,还是通过手动写脚本的方式签名,参照 Mac App Store Submission Guide 即可。

图标

图标问题也卡了几个小时,主要是因为提交到 iTunes 之后提示说,需要提供 512 和 512@2 的 icns 文件,而打包结果里没找着。

这就奇怪了,我明明放进去了为什么它找不到呢?后来我仔细看了下我的 icns 文件发现是 png 转 icns 的时候出了问题。

在我使用 iconvert icons 的时候,导出的图片没有 1024*1024 的图:

使用 Electron 开发一款理财计算器

而在我使用 cloudconvert 的时候,则只有 1024*1024 的图:

使用 Electron 开发一款理财计算器

嗯?!

使用 Electron 开发一款理财计算器

这不是坑爹吗!

于是只好手动撸,刚好电脑里有以前做 iOS Icon 时装的 prepo ,可以将 1024 的 png 导出各个尺寸的图片并且放到 iconset 里:

使用 Electron 开发一款理财计算器

然后只要用一行自带的命令就能将它们打包成 icns 文件:

iconutil -c icns icon.iconset 

大功告成。

小结

因为最近忙着搬家的事情,这篇小结就暂时写到这里。

总的来看, Webpack+Vue+MDL+Electron 开发跨平台应用是一种很不错的开发体验。

虽然一路踩了很多坑,但是在应用上架的那个时刻。

我只想说。

Excited!

原文  http://blog.callmewhy.com/2016/07/01/make-calculator-with-electron/
正文到此结束
Loading...