前言:
从9月初开始到现在,我一直在寻找一个适合自己的,可以跨平台的开发APP的js框架。
虽然之前自己也有陆续接触过Weex,React Native,Flutter,NativeScript,Appjs。但是或多或少都提不起我个人的兴趣。原因可能是我不太喜欢RN的书写方式,不太想写css或者去写declarative形式的UI,更加的不喜欢去写html。还有就是难以接受的复杂的开发环境以及高成本的安装方式,调试形式,和乱七八糟的插件文档,总之我一直没去开始尝试,很大一部分是个人的喜好原因。
我其实一直想着能有一款框架只需要编写javascript,就可以完成APP的开发,比如之前我一直在关注的nodeapp,我觉得这才是理想中我想要的js开发者形式的框架,我就是想在app里快乐的书写js,只有js。
可以看出我非常偏执的喜欢js,能拿js干的事绝对不要别的乱七八糟的东西来辅助,直到有一天无意看到了tabris.js,简单阅读了一下文档,我发现这玩意简直就是为了我这种怪物量身打造的。
本文涉及内容分为四个部分:tabris的介绍和一些使用心得,使用nodejs开发简单的API范例,以及代码迁移到码云后,管理代码和项目的一些体验感受。
本文非常适合个人开发者,或者认同js天下无敌的人阅读。
1. 什么是tabris.js
一开始接触的时候,我本来也想着是不是能够吃现成的。看看有没有前辈也用过这个框架开发了什么好东西。但是经过长时间的搜索,发现在知乎,国内技术社区谈到tabris.js的文章简直可以说基本没有。已知的是2016年底infoq上有过一篇展望前端发展的文章里提了一句,网易前端技术部在16年底某篇BLOG下,有提到且并不是专门介绍tabris.js的。所以tabris基本可以说没有什么二手资料可以让你学习的,我也希望我这篇文章能够帮助大家快速的了解tabris.js到底是什么,好在哪里,如何使用。
mobile app development in JavaScript 官方的首页介绍说的非常明白,tabris.js是一款跨平台的移动端app开发框架,兼容ios,android和win phone。
首先它并不对你的javascript代码进行编译转换成native code,而是在app里直接执行你的javascript code,所以是支持允许热更新技术的 Patching a Tabris.js App。
tabris.js完全不需要依赖webview,就可以直接运行javascript代码来进行纯UI的编码,和进行原生代码功能的调用,在Android上使用了J2V8作为JS引擎方案,在iOS上使用系统自带的JSCore来完成javascript代码的执行。
简单的了解了tabris.js的原理后,我们再来看一下tabris的几个我觉得比较关键的点。
- tabris.js是完全开源免费的,使用BSD 3-clause License。
- 安装和开发方式非常简单,只需要本地有nodejs,因为开发是基于它们的developer app来的,所有的开发过程都是在真机进行的调试开发,本地也不需要下载庞大的SDK。
- 支持模块化开发,支持远程和本地编译,支持cordova插件(没有DOM的),支持本地的node_modules包(纯javascript的),支持canvas,支持fetch,xmlhttprequest,localStorage,fs,基本的ES6语法环境,支持ts还有jsx,支持对widget进行selector,总之非常的符合js程序员的思维。
- 内置部分cordova插件,如摄像头调用,扫码,陀螺仪,消息提醒等。也支持内置的一些实用widget,比如collectionView,scrollView,input,text,image等等。也支持扩展自己的widget和cordova插件。
- 如果你愿意,你完全可以只用javascript来编写你的APP,编写过程是基于事件驱动的,并且所有的常用UI都可以直接以类的形式继承到新类里直接使用,也可以自己使用canvas绘制UI和开发游戏,内置了丰富的动画效果库,当然也可以自己自定义。
- 文档写的非常好,编写文档和SDK的同学明显就是javascript工程师出身,非常符合我的胃口,社区响应速度很快,我提过的2个issues都在24小时之内回复和处理,官方非常活跃,开发和提交速度比较频繁,而且是团队开发的形式。
2. tabris.js开发体验
tabris.js我上手基本就是几个小时的事,安装方法官方非常简单,就不叙述,我这里以我自己的APP为基础进行讲解。
首先开发之前可以先扫一遍每一个widget的文档,知道都能做什么。
然后可以跑几个他们官方的eclipsesource/tabris-js 完整例子和eclipsesource/tabris-js 代码片段,不过就我个人而言,这些demo都不是一个完整的APP开发案例,真的只是demo,所以下面我还是基于我自己实战开发的兔耳日记,来简单的讲解一下整个开发体验:
目录结构比较清晰,安装完成后入口文件是src下的app.js,然后就没了,其他目录结构自己可以随意定制,根据官方的例子我也没看出什么套路,所以我也干脆自己设计了一套结构和代码维护方式,我这里就拿登录退出这个流程来简单讲一下:
代码真的非常好理解,我在启动时对登录态做一个初始化判断, 然后检查登录态,如果登录了就进行tabs的视图调用,如果没登录就调用登录界面。
这里和web开发不太一样的是没有路由的概念,和开发游戏有点类似,app中我理解都是场景的转换,所以每个场景我都使用一个class来表示,这样方便复用,调用以及销毁注销,每个调用后的场景都是一个独立的实例,然后不同的实例之间用事件进行关联。
可能一直做前端开发的同学在这里需要绕一下,如果之前就开发过app的人可能上手就非常快了。
判断是否登录和正常的web开发也不一样,首先在app里是没有session的概念的,也没cookie,所以在这里我选择localStorage来进行状态的保存,使用方法就和平时没两样,jwt是大家平时通用的token验证形式,如果本地有并且解析完token没有过期,则返回true,如果解析完过期或者本地没有jwt token,则是没登录状态,jwt-decode是一个npm上的纯js包,在tabris里是都是可以直接安装调用的,这里开始写成异步的了,是因为可能后期还要加入刷新token的机制,刷新需要异步访问远程API的。
上面是一个login的部分代码,首先引入tabris的widget,比如Button,ImageView等,然后定义我们的登录类,初始化的时候我们保存了一个Composite到实例中,Composite大家可以理解成是一个图层,里面可以随意放置组件,然后还可以通过对这个Composite进行过滤删选组件,非常方便管理UI比较复杂的地方。
destory方法是提供给别人调用进行组件销毁用的,dispose是删除并销毁,对应还有方法可以删除不销毁,方便之后复用的,可以参见widget类的文档。
init方法里就开始进行组件的绘制过程了,看起来非常的熟悉这不就是面向DOM编程咩?new 一个组件然后定义它的样式和属性最后再appendTo到父组件里,如果想实现居中X轴,Y轴居中偏移120,就定义centerX,centerY就可以了,非常方便。如果使用过YUI的同学会非常熟悉这种形式。如果需要给组件绑定事件,直接on就可以了,支持的事件非常丰富:Gesture and Touch Events
下面这里是对登录按钮进行了select事件的处理,然后简单的进行一下校验,最后再用我们对fetch封装后的post方法进行api接口调用,成功后对jwt值进行保存,然后调用自身的destory方法,再初始化登录后的实例。
下面对外进行了constant的管理,对外暴露init和destory方法,其实这部分后期是可以再抽象出来一个base类的,这里就简单的给大家演示下。
退出部分的代码也非常的简单,清楚本地ls,对实例进行切换。因为一个app其实主要的场景可能没几个,如果有的话也是以树形的形式一级一级向下维护的关系,所以最顶层我这里就设置了登录和未登录2个状态。
因为篇幅有限,代码等完整开发完毕后我会开源,其中的坑当然也有,我下面简单的总结一下:
- collectionView中的cell无法绑定独立的事件,所以如果不是纯列表展示,建议用scrollView Composite的方式来进行自定义列表的渲染。
- collectionView不指定高度,渲染时会有重叠bug,已经提交给官方。
- 按钮,图片,文本,控件等支持的css样式比较可怜,所以建议都使用背景图或者图层叠加的方式实现设计。
- input支持的多行形式比较傻,如果要做像知乎一样的APP端发布器肯定需要自己扩展,目前的形式加滚动条都要和scrollView配合使用,非常的反人类,不过后期我都打算自学写widget了。
- 调试很方便,打包速度也比较快,等我上架了应用后会简单提炼一个build的中文教程吧,包括内置apple pay和google pay等。
- 对使用者的js抽象能力要求较高,虽然支持jsx,但是我肯定是不会用的。。而且其实本身对样式的定义,widget就给了classList这种属性支持汇总管理的,只不过我暂时还没用。
基本上缺陷比较少,如果做纯展示类的项目,开发速度扛扛的,当然如果很多空间都需要定制化开发,那么还是需要掌握native开发的,但是纯UI层面的开发就完全不必了,这里的layout方式和web也不太一样,参见:Layout - Tabris.js Documentation 个人来说感觉比web布局方便多了。。因为全部都是基于相对和视图位置来布局的,说实话我很烦浮动那种布局方式,也可能是我好久没写css了,我很喜欢目前这种layout方式。
3. 使用restify开发API
基本上tabris的使用和体验就如上,后边说一下另外一个老牌nodejs框架restify,一个专门用来编写API的类express框架。
会用express的人太多了,因为类express,所以就简单说一下哪里和express不太一样吧,开发方式基本一致,主要是增加了N多的中间件配合restfulAPI的开发,而且增加了一些频率,网段,IP等限制节流的方法,又引入了API版本管理以及常见的API错误和常见错误号等。
所以大家如果对express比较熟悉,那么选择restfiy开发纯API服务还是比较靠谱的,上手也非常快,官方文档 Restify 。
下面还是拿登录接口做一个例子:
对所有请求做一次jwt的验证,这里使用了一个jwt的express插件叫jwtAuth,我看了下源码,如果header里没有token,则对query进行验证要自己做,做完补充后,我再手动挂到req的decoded字段中的,这里就完成了对所有api的jwt验证。
然后数据库orm用的mongoose,定义好user的model之后,api是这样写的:
对post过来的用户密码进行校验和md5加密,然后对数据库匹配,最后返回用户的非敏感信息,登录过期时间,然后返回jwt给客户端保存。
基本上这就和上面第二部分登录对应上了,使用nodejs开发API真的是非常的简单。
4. 使用码云管理完整的开发项目
上面介绍了开发APP客户端和服务端的一些代码片段,最后说一下项目管理和代码管理部分,因为github要收费,gitlab的速度我有点无法接受,正好有一次机缘巧合,朋友推荐我用一下这个国内的代码托管服务还不错,叫码云 码云 | 开源中国基于Git和SVN的代码托管和研发协作平台 。
后来我就体验了一下非常的不错,这里也给大家安利一下吧。
首先码云提供的免费版相比github就已经足够个人开发者和小team使用了,5人成员上限,5G容量,单文件最大100M,单项目最大1G,社区与邮件支持,我就用的企业免费版,说一下感受吧。
首先注册完成后,我添加了2个项目,一个是客户端项目一个是API项目,在时间线上每次登陆都可以看到我的提交动态,包括成员任务的处理和状态,然后是支持非常方便的从其他地方导入项目,比如我就是从gitlab导入的码云的,不过其实对于大家来说直接设置一个新origin的remote地址就可以了。
整个企业版的完整功能,免费版是完全都解锁的。
比如文档协作,还有任务管理,开发量统计等,非常适合小型敏捷迭代的项目。
感觉比github的issues好用很多,而且同样是可以跟踪到人,非常方便,还有时间统计。
统计的维度有代码提交次数,新增任务量,任务完成量等。当然因为项目只有我一个人,所以我大部分都是拿码云来当托管仓用的,没有太多看这些时间相关的管理任务,因为怎么搞都是我自己一个人。。
最后是仓库的界面,用习惯了github切换到码云也没有什么特别的阻碍,设置好ssh公钥就ok了,而且码云也有对应的教程,码云平台帮助文档_V1.2
在代码管理方面,码云延续了 Git 的优点,并增加了分支保护的功能,和更细粒度的权限管控,让团队协作更安心。
在任务管理方面,更轻、更灵活,支持关联任务和多层子任务,同时也具有任务多类型功能,可以让企业用户方便地维护自己的自定义类型以及自定义状态。无论拿来做需求管理还是 Bug 跟踪,都能够轻松实现。并且任务(Issue)直接关联到项目、到分支,并与 Pull Request 相关联,项目 → 任务 → 代码 完全一体,让开发前所未有地流畅、便捷。
另外码云的全自动仓库快照功能,也同时为企业代码安全保驾护航,个人十分推荐,虽然我还没有使用全面,但是给我的感觉很靠谱。
总结
总的来说,使用tabris.js和restfiy的初衷就是选对一个适合符合自己的开发习惯和感受的框架,文中我也说明了,如果大家喜欢tabris和restfiy的话可以和我一起学习交流。
码云的项目地址:
https://gitee.com/terj/tuerAPP
https://gitee.com/terj/tuerAPI