基于HTML5开发手机应用的新模式

1     引子

不知什么时候开始,iOS和Android火了,手机应用程序员的薪水突地坐上了神舟5号,一夜之间一升再升,直接摆脱了地球引力,飞出大气层。然而,不是每个公司都有这样的实力和魄力,养得起程序员中的高富帅。

屌丝老板想做手机应用充高富帅,但养不起高富帅程序员;屌丝程序员想跻身高富帅,但不会做手机应用。于是,物竞天择的屌丝群中,冒出了一撮聪明人,他们认为用浏览器也可以做手机应用。事实证明,这群人的想法行得通,尽管头上还顶着“非主流”三个字。

2     预览和调试

2.1   难以忍受的模拟器

做手机开发的童靴们,最不可忍受的应该是模拟器了;每次修改和调试程序,模拟器都需要对应用进行卸载和安装,并同步调试进程,最恶心的是偶尔还要重启模拟器,这真真是一个磨砺心性的强大武器(高富帅也有难受的时候?)。

屌丝们的梦想是基于HTML的,可以省去很多工作,比如代码的编译,打包,重新发布等工作。但不可避免,界面的调整和功能的调试,大部分时候还是会回归到模拟器中来(事实上,直接通过USB连手机调试,比模拟器快N倍,不过这样一来对屌丝们的装备就有所要求了)。

2.2   姑且一试

基于HTML开发手机应用,不论是网页应用,还是基于各类框架(PhongGap、AppCan、Rexsee之流)的本地应用,其事实上都有一个重要的基础媒介:浏览器(这大概也是WebKit名声大噪的原因之一)。

到这里,童靴们大概还没明白我要说什么?

其实我想说:咱们就直接用Chrome充当模拟器吧。

我们知道(iOS和Android)手机上的浏览器都是基于WebKit内核,唯一的区别就是WebKit的版本不一样。当然,这会导致一个比较严重的问题,就是WebKit不同的版本,对HTML和CSS标准的支持有些差异。

恩,这也让我们学会一个铁则:尽量采用兼容性比较好的HTML标签和CSS属性!

既然如此,那么用Chrome做模拟器,就显得理所当然了。尽管手机和PC的分辨率不一样,在一些细节的展现和处理上会有些微差异;但胜在PC的速度够快够方便,不管是调试程序逻辑,还是界面流程,都是流畅自如畅快淋漓。

3     方法与模式

3.1   js的渗透程度

很多童靴害怕接管太多的事件,希望最大程度的借助浏览器及各种框架(jqMobi、jQueryMobile之流)本身的功能,并且潜意识里觉得(更多的是期望)二者已经为我们提供了足够好的封装。

然而事实并非如此,手机不同于PC,用户喜欢用更少的流量和更快的速度,浏览更多的内容。如果仅仅是采用浏览器和框架提供的功能,至少我们就无法使用缓存(说localStorage更贴切点)。所以我们必须认真考虑js代码的渗透程度,也可以理解为程序中有多少链接是由js来控制的?这没有标准答案。但好在可以给童靴们提供一条建议:但凡页面内容是动态请求而来的,请接管这个链接。

3.2   代码的一致性

上面提到用Chrome充当模拟器,事实上代码在Chrome和手机浏览器上运行,还是会有一定的差异,特别是我们采用了框架的情况下(如:PhoneGap)。

解决差异的办法,可以沿用古老的门面模式来实现。

假设我们需要在页面上输出设备名称(我们知道,在Chrome中是没有device对象的):

var Device = {

name: function() {

if(isMobile()){

returndevice.name;

}else {

return”chrome”;

}

}

};

这样,我们在后续的js代码中,都可以通过Device.name()来获取设备名称,即使我们是在Chrome中运行,也能得到一个设备名称,从而获得代码的一致性。

3.3   通向彼岸的路

到这里,大概有童靴已经能预见我们要说的彼岸之路是怎样的了。

是的,我们可以这样:

²  设计一个全局对象,通过门面模式,对外提供应用所需的全部功能调用。

²  接管所有动态内容的页面链接,并用js实现页面内容的填充。

²  尽量采用有良好兼容性的HTML标签和CSS属性。

²  采用Chrome充当模拟器。

有童靴要讲,我不这样做,同样可以通向彼岸的说。

没错,这不是唯一的路,但这样做,绝对可以让你的开发速度提升一截;最关键的是你的代码更优雅,也更稳定。

4     构筑模式

这也有模式吗?这个可以有。

我们稍微梳理一下,就可以知道在HTML应用中需要用到的功能有:

²  应用名称及版本。

²  远程服务器地址及各请求路径。

²  缓存(可分为localStorage和cache)及数据库。

²  其他公用功能,如HTTP请求等。

²  应用中需要用到的功能。

如果基于这几点出发,我就可以设计一个全局对象,囊括上述所有功能调用和属性。那么,在整个应用的生命周期里,我们的其他js代码就可以简单的通过这个对象来获取所需数据,仅仅只关注与业务逻辑相关的UI的控制即可。换句话说,我们把底层功能都封装在这个全局对象上,而UI和流程的控制,则交给其他的js代码(显而易见的,js代码也被分层了,是不是?)。

恩,用范例代码说话,就是这样:

var Html5App = {

appName: ‘Hello’,

appVersion: ‘1.0’,

 

baseUrl: ‘http://xxx/mobile/’,

 

servPath: {

LOGIN: ‘login.do’,

LOGOUT: ‘logout.do’

},

 

ensureUrl: function(url) {

},

 

storage: {

/*

* 获取已存储对象

*/

get: function(key) {

},

 

/*

* 存储对象到本地

*/

set: function(key, val) {

},

 

/*

* 清除所有已存储的数据

*/

clear: function() {

}

},

 

cache: {

/*

* 获取已缓存的对象

*/

get: function(key) {

},

 

/*

* 存储对象到缓存

*/

set: function(key, val) {

},

 

/*

* 清除所有缓存数据

*/

clear: function() {

}

},

 

user: {

login: function(user, pwd) {

},

 

logout: function() {

}

}

 

};

5     后记

英雄出身草莽,屌丝程序员中同样不乏聪明人,应该很快会看到基于这种模式而延展出来的框架,我们拭目以待……

标签