在这个angularjs的项目里,我把controller分类两类,一个是页面级别的controller,一个是对话框级别的controller。页面级别的controller就是用户直接点菜单,路由到某个页面,需要用到的。对话框级别的就是在页面中使用bootstrap对话框组件需要的controller。
页面级别controller
define(['require','angular','modules/hardware/disk/disk.service','modules/alert/alert/list/list.service'],function (require,ng){
var module = ng.module('app.hardware.disk');
module.controller('DiskDetailCtrl',DiskDetailCtrl);
function DiskDetailCtrl($scope,$interval,$filter,$mdDialog,modalUtils,chartUtils,diskSrv,alertListSrv){
$scope.vm = {};
activate();
function activate(){
}
}
DiskDetailCtrl.$inject = ['$scope','$interval','$filter','$mdDialog','modalUtils','chartUtils','diskSrv','alertListSrv'];
});
省略了具体的业务逻辑,只是展示一下controller的代码结构,具体代码的规范可以参考前面的文章。这里之所以使用$inject这种方式,还有一个原因是在单元测试的时候,因为整个应用使用了requirejs这种异步加载机制,有的controller里面会用ngload异步加载一些文件,那么跑测试的时候,无法控制在加载完成后在运行test case,所以用$controller的方法测试controller会报错。
对话框级别的controller
在使用bootstrap对话框组件的时候,会有很多参数,而且用起来比较繁琐,所以应该自己封装一下——
modalUtils.showDlg({
tpl:'modules-lhv/network/extranet/extranet-creation.html',
deps:'modules/network/extranet/extranet-creation.controller',
ctrl:'ExtranetCreationCtrl',
size:"md"
}).then(function(result){
},function(){
});
function showDlg(dlgParams){
var deferred = $q.defer();
var $uibModal = $injector.get("$uibModal"),
modalParams = {
templateUrl:$templateCache.get(dlgParams.tpl) ? dlgParams.tpl : (dlgParams.tpl.indexOf("/") != 0 ? cmpConfig.appPath + dlgParams.tpl : dlgParams.tpl),
controller:dlgParams.ctrl,
backdrop:'static',
resolve:{
params: function(){
return dlgParams.params || {};
}
},
size: dlgParams.size || "md",
windowClass: dlgParams.windowClass || "",
};
if(dlgParams.deps){
modalParams.resolve["$$deps$$"] = function(){
var deferred = $q.defer(),
$$deps$$ = angular.isArray(dlgParams.deps) ? dlgParams.deps : [dlgParams.deps];
require($$deps$$,function(){
deferred.resolve();
});
return deferred.promise;
}
}
var modalInstance=$uibModal.open(modalParams);
modalInstance.result.then(function (result) {
deferred.resolve(result);
},function(reason){
deferred.reject(reason);
});
return deferred.promise;
}
function showSmallDlg(dlgParams){
dlgParams.size = "sm";
return showDlg(dlgParams);
}
function showConfirmDlg(options){
......
}
function showErrorDlg(options){
......
}
function showInfoDlg(options){
......
}
主要想说的是,bootstrap的对话框组件需要在使用前把controller加载进来,如果在页面级别的controller里面把对话框需要的controller通过define提前加载进来,会造成不必要的资源浪费,因为用户可能根本不去使用某些对话框提供的功能。所以上面最重要的功能就是利用resolve方法去动态加载controller。最好还能对info,error,confirm等类型对话框做一层统一的封装,方便调用。
这里还要提一下controller继承的问题,controller本身不提供继承的功能,但是还是有方法可以实现的,可以参考一下这篇文章:
$controller('BaseController', { $scope: $scope });
前提是BaseController需要提前用define加载进来,然后把这句话写在controller定义函数的最一开头就可以了。其实就是把父controller里$scope上的东西加到了当前controller的$scope上。