AppCan移动开发技术体系架构:MPA+Backbone+Zepto 模式

orchid_yu 发布于 2016/05/11 11:52
阅读 441
收藏 1

在最近的一次分享中,AppCan CTO赵庆华首次讲解了AppCan的体系架构,即MPA+Backbone+Zepto的技术路线。算是科普贴,能够帮助开发者弄清很多底层的基础知识,也能对不同架构的开发工具的优缺点有大致了解。

先来谈谈移动开发常见的两种方式:SPA和MPA。SPA即为单页面Application,常见移动开发工具中比较典型的是国外的PhoneGap、国内的Wex5,两者共用cordova引擎;MPA为多页面Application,以AppCan为代表。这两种方式都是对H5应用开发来说的,其他原生开发基本都是MPA的。

SPA(单页面)是使用JS技术来模拟多界面的效果,特点如下:

1. 主页面主体仅加载一次,主体需要依赖的基础JS文件,例如Jquery都在开始时加载。

2. 各界面本质上是独立的HTML代码片段,通过锚点 < a href=" ">next 的hashchange事件,触发AJAX动态加载片段并嵌入到主体框架中,实现界面的变化。

3. 独立的HTML代码片段所需要依赖的JS文件、CSS文件,都可以在HTML代码加载前通过一些框架进行加载。

4. 界面间过场动画都是由JS进行实现。

SPA(单页面)的优点:

1. HTML代码不是一次加载,而是随用随加载,减少了初次打开页面时加载量,可以降低界面加载时间,提高体验。

2. 过场动画可以由JS实现,而传统MPA模式是浏览器处理界面跳转,没有过场动画。

SPA(单页面)的缺点:

1. 全部运行于一个页面环境中,不可避免的面临HTML元素ID冲突、CSS冲突、JavaScript变量冲突。

2. 为了解决这些冲突,需要进行CSS样式处理、对元素ID进行动态化、使用第三方框架RequireJS等进行模块封装。这又造成了开发工作的浪费和技术学习成本提升。

3. 单页面模式下,通过AJAX不断加载HTML代码片段到主体框架中,为了保证性能,需要有效的完成页面的卸载和加载,避免界面不断累加引起的冲突和性能损失。这也加大了开发人员的工作难度。

4. 界面异步加载,脚本异步加载,造成调试复杂,难于定位。

5. 使用锚点路由,实现界面间变化触发,需要使用路由管理。由于界面路由复杂, 在知识转移时,开发人员需要更多时间才能看懂代码。尤其是大应用复杂的路由,会非常折磨人。

6. 所有界面都在本地,而不是存储在服务器上,因此SPA(单页面)的随用随加载提高的优势,在Hybrid应用上几乎体现不到。

MPA(多页面)模式:

1. 关于动画:SPA模式的界面间动画通过JS实现,传统浏览器中的MPA网站确实无法实现。但在本地应用中,可以很方便的通过原生进行实现,这种实现具有通用性,且相比JS实现的动画效果体验更好。AppCan已经在引擎中封装了多种过场动画,开发人员不需要投入精力在这部分的开发上。

2. 关于带宽:MPA模式页面在本地,数据也是通过AJAX方式从服务器获取并在前端拼装,与SPA方式相同,不存在B/S MPA模式占用带宽大的情况。

3. 关于定位:MPA模式中各界面独立开发,可以进行独立调试,断点跟踪,更容易定位问题。

4. 关于开发:由于不需要满足SPA的懒加载等能力,开发人员不需要投入精力进行学习,也不需要维护这部份代码,更专注于具体需求的实现。

由此看来,采用SPA模式的H5开发工具,为了填坑,需要很多技术的推叠与适配,才能保证基本运转;AppCan的初衷就是为移动开发设计,自主研发,整体架构,在一开始就去掉了不需要的网页技术,开发者人员用最基础的技术就可以构建复杂的应用。

在MPA的技术路线之上,AppCan选择了Zepto和Backbone作为基础支持库。

Zepto是JQuery的移动化版本,去除了PC相关的特性。MPA模式也不能没有前端MVC框架支持。为了保证前端开发的规范化、易读化,合理划分网页切图工作、界面交互开发工作、服务器数据对接工作,避免各工作之间的耦合冲突,AppCan选择了MV*框架中的Backbone作为基础框架。选择Backbone而不是选择AngularJS等其他MV*模型,看重的就是它的小而精,易学易懂。

Backbone基础设计中,是按照如下结构进行分层的。

最上层是DOM层,即开发人员切图输出的静态HTML代码。View层负责完成DOM层用户人机交互,实现界面与数据模型的关联。

Model/Collection层负责维护数据。最下层的Jquery/Ajax完成最终与服务器的通信。在实际开发中,对上述模型进行了调整,如下图:

在DOM/VIEW层,AppCan保持与Backbone框架一致,在Model/Collection层,要求开发人员重载Sync函数。增加Service层负责调用AppCan.Request.ajax与服务器通讯。使用AppCan.AJAX代替$.ajax完成数据交互。

上述模式主要原因:

1、$.ajax调用的是浏览器本身的AJAX对象,很难增加底层的加密和安全校验算法。

2、$.ajax对浏览器会产生影响,降低体验。使用AppCan.request.AJAX最终调用独立线程的原生通讯模块,体验会更好,同时自动添加应用校验等标识。

3、增加Service层,主要是由于国内大部分厂商,尤其是很多地方服务平台并不支持restful规范的API输出,要应对不同接口封装独立Service的需求。

4、为了使模型能够调用对应的Service,需要重载sync函数,可以同时在数据模型层级加入缓存等功能。

如下的代码范例演示了dom view model service的关系:

个人信息VIEW —personinfoView

个人信息数据模型—userInfoModel

个人信息查询和修改服务

上述代码中,可以看到一个数据模型可以对接多个服务,同时一个数据模型也可以对接多个VIEW。例如用户信息VIEW和用户信息编辑VIEW,View的操作都会映射为对于数据的操作。Model根据数据操作不同,调用不同服务实现与服务器API的对接。

在View层,开发人员不需要关心服务器到底如何编写接口,只需要调用fetch、save等几个接口即可,所有的数据格式操作都屏蔽在model和service层。这样可以有助于切换数据源时,不对view层产生影响。开发人员只关注界面操作和用户交互工作。

在Model层,借助localStorage,可以很方便实现数据的离线处理:

  var userInfo = appcan.getlocVal(“CACHE_USERINFO_”+option.userId) || ‘{}’ ;

  this.set(JSON.parse(suerInfo)) ;

  个人信息数据模型-userInfoModel

通过localStorage实现用户信息的初始加载,提高体验。通过重载Sync接口,把数据操作划分为“增、删、改、查、补”五种操作,对应不同的Service实现与服务器的对接,Model开发人员不需要关心具体服务器实现。

在Service层,实现不同的服务接口与后端服务器接口进行对应。在Service层可以很方便的实现数据挡板,满足前端开发调试要求,也可以快速实现无后台依托的DEMO应用的构建。

通过上述模型划分,很容易保证开发人员基于基础应用参考模板进行二次界面定制。

通过这种方式,开发人员仅需使用Jquery常用函数,会操作DOM就可以了,不用关心窗口加载顺序、回收等,可以实现开发人员的大批量快速培养。

加载中
返回顶部
顶部