基于Hybrid开发模式的AngularJS开发,相比传统Web站点的开发模式有着很明显的差别,最主要体现在Window对象的作用域不同,在传统web开发中,所有angular module都是共享同一个Window对象,而在移动开发领域,我们更倾向于基于多WebView并存的形式来做页面内容组织,这样做最大的好处便是能尽可能多的缓存页面状态,实现类似纯原生应用的快速页面呈现体验。
基于此论断,我们将同一个模块的页面放在同一个webview中承载,理想状态下,每一个模块均使用一个独立的webview来承载并缓存,页面呈现时基于webview缓存机制来做呈现,尽可能减少html加载时间以求达到类似原生页面的效果,因为IOS的webview加载时间较快,所以目前暂时是基于此方案来做全局路由跳转与页面状态缓存。
而对于Android这类单个webview内存占用很大的场景,可以将webview的缓存复用与Fragment的页面状态缓存进行剥离,从而达到统一路由管理与内存可控并存的效果。
当前APP采用Hybrid开发模式,web端采用AngularJS框架进行开发,结合AngularJS的模块解耦与路由控制特点,初步发展出结合移动端开发特点的MVC开发模式,以提高APP开发效率与交付质量。
AngularJS的一大特点就是功能模块化设计、依赖动态注入,针对基于本地html页面的hybrid开发场景,我们尝试将业务需求基于业务流程进行模块级划分,每个业务流程作为一个独立模块单元来进行设计,模块间的页面跳转与状态同步由Native端的统一路由模块进行管理控制,模块内的页面跳转采用Angular自动的UI-Route机制处理,模块内的状态同步基于数据模块绑定来做简化处理。
对于模块内的业务开发,结合AngularJS数据双向绑定的特点,初步采用基于MVC架构分层的开发模式来做代码开发。
结合AngularJS的双向数据绑定能力,Hybrid开发中,对于Angular业务Module的开发也采用MVC架构,总体职责分配是:
Module层
数据模型层统一进行模块级数据对象的状态管理,数据状态的变化通过AngularJS的数据绑定能力自动更新到页面,这是数据建模产生的最大价值。
Controller层
页面控制器层主要职责是完成数据绑定关系映射、处理用户交互事件;当然考虑到AngularJS模块机制的特殊性,对于模块级的控制行为也可以划归为Controller层,主要包括模块内路由行为初始化、模块级生命周期事件监听与处理。
View层
视图呈现层在web端,对应就是html结构设计与css样式处理。
Service层
服务请求层,主要职责是管理与服务端交互的请求,目前主要是HTTP请求。这一层后续的重构优化空间还很大。
原生交互层
该层用于统一管理h5与原生进行的交互,主要基于思迪框架的插件机制,在此基础上进行业务友好性封装。
下面以定投列表模块代码为例,进行具体讲解。
hjMPModule.factory("dataHolder",['hjMPService',function(hjMPService) {
return {
mpList: [],
selectItem : {},
dataRefsh: false,
scrollTop: 0,
showErrorMsg: false,
errorTip: '',
//根据索引号查询指定定投项
getMpItem : function(contractNo){
for(var i = 0; i < this.mpList.length; i++)
{
var item = this.mpList[i];
if(item.conno == conNo)
return item;
}
return null;
},
removeMpItem : function(conNo)
{
var item = this.getMpItem(conNo);
if(item != null)
{
var index = this.mpList.indexOf(item);
this.mpList.splice(index,1);
}
},
setDefaultData : function()
{
this.mpList = [];
this.dataRef = false;
this.scrollTop = 0;
this.showErrorMsg = false;
this.errorTip = ''
},
queryMyMpList : function(callback, callbackError)
{
var self = this;
var hjUserId = hj.UserUtil.getUserId();
hjMPService.queryMyMpList({
userId: userId
}).then(function(data) {
if (data.mpList != null)
self.mpList = data.mpList;
if(callback)
callback(data);
}, function(error) {
if(callbackError)
{
callbackError(error);
}
});
},
updateMpStatus :function(status, payPassword, callback, callbackError)
{
var self = this;
var promise = hjMPService.updateMpSt({
userId: hj.UserUtil.getCmfUserId(),
conNo: self.selectItem.conno,
contractSt: status,
payPassword: payPassword
});
promise.then(function(data) {
self.selectItem.contractst = status;
if (status === 'N') {
self.selectItem.contractst= 'N';
} else if (status === 'P') {
self.selectItem.contractst= 'P';
} else if (status === 'C') {
self.removeMpItem(self.selectItem.conNo);
}
if(callback)
callback(data);
}, function(error) {
if(callbackError)
callbackError(error);
})
}
};
}]);
模块初始化职责:
1、模块内路由规则设定;
2、模块内路由跳转监听;
3、模块级生命周期事件监听;
4、模块级页面状态维护;
//我的定投列表
mpModule.controller("getMpListController",["window', 'hjMPService', 'useLoaddFact', function(scope, state, dataHolder, window, hjMPService, useLoadFact) {
$scope.dataHolder = dataHolder;
$scope.fVoteNoData = false;
dataHolder.contractst = '';
//修改协议状态事件
scope.modifyStatus = function(obj, type) {
dataHolder.selectItem = $obj.item;
dataHolder.scrollTop = scrollObj.scrollTop;
dataHolder.dataRefsh = false;
if($obj.item.contractst == "A" && type !== 'undo') {
return;
}
if (type&& type === 'undo')
dataHolder.contractst = 'C';
scope.parent.go("modifyStatus");
};
var hjMPModule = angular.module('hj_Fund', ['hj_Location']);
hjMPModule.factory('hjMPService',['http', 'q', 'hjServer', function(http, q, hjServer) {
function getPromise(url, jsonObj) {
var deferred = $q.defer();
$http.jsonp(url, jsonObj).success(function(data) {
if(data.resultCode === "00") {
deferred.resolve(data);
}else {
deferred.reject(data.resultMsg);
}
}).error(function(data){
deferred.reject("系统错误,请稍候再试!");
});
return deferred.promise;
}
后续重构方向:
1、基于业务集进行服务模块搭建;
2、基于请求状态来做请求管理,防止重复请求;
$stateProvider