AngularJS模块加载

原创
2014/11/07 11:56
阅读数 1K

    之前有一篇博客写到了关于AngularJS的权限控制,简单说就是在AngularJS应用启动之前先获取到当前用户的权限队列,然后在每一次route变化时进行相应的校验,具体的可以看Angular中在前后端分离模式下实现权限控制 - 基于RBAC.

    虽然给出了代码,不过其中还是有一个坑的,就是获取permissionList这一部分.再简单点说就是我们希望在AngularJS应用启动执行之前,确切的说是在index页面加载之前就取到一个包含用户权限的数据.那么这个数据存放在什么地方?因为要在AngularJS启动之前就存在这些数据,route的路由等才能进行校验,不然等相应的一些Controller模块加载后才有permission,用户已经进入页面了,这岂不是为时已晚.

    当时考虑了这么多,所以最开始的做法是定义了一个全局变量,然后通过Ajax请求将权限的相关数据请求过来,最后在启动Angular App.

    这样的做法虽然可以解决问题,但是明显的污染了全局变量.AngularJS本身所有的module,service,controller都是通过模块定义的,没有任何一个暴露在全局中,所以理论上这种permissionList的东西也不应该让它暴露.那么就需要有什么东西,能让我在AngularJS启动之前就将数据存入到AngularJS应用中.

    能做到这一点的就是通过模块配置了,AngularJS模块可以在被加载和执行之前对自身进行配置.

var permissionList;
angular.element(document).ready(function() {
  $.get('/api/UserPermission', function(data) {
    permissionList = data;
    angular.bootstrap(document, ['App']);
  });
});


  配置块(config)

    在模块的加载流程中,AngularJS可以在模块注册时对其进行配置,这是AngularJS的工作流程中唯一可以在应用启动前对其进行修改的阶段.代码类似于:

angular.module('myApp',['ngRoute'])
  .config(function($provide){
    // do something
  })

    之前我们更多是使用config进行了路由的配置,其实仔细想想对于路由也一定是要在页面进入前控制.所以道理上市一样的,既然如此当然还可以在config中定义service用来存一个变量或者一个提前定义一个directive.

angular.module('myApp.directive', [])
.directive('appVersion', ['version', function(version) {
  return function(scope, elm, attrs) {
    elm.text(version);
  };
}]);

    上面的代码在AngularJS编译会执行,他们在功能上等同于下面的写法:

angular.module('myApp.directive', [])
  .config(function($compileProvider){
    $compileProvider.directive('appVersion', ['version', function(version) {
      return function(scope, elm, attrs) {
        elm.text(version);
      };
    }]);
  })

    注意到这里多出一个$compileProvider,它辅助AngularJS模块完成了加载的过程.这一过程中AngularJS以书写和注册的顺序来执行函数,所以无法注入一个还没注册的提供者.

    在使用config对模块进行配置的时候,不是所有的对象都可以被注入到config()函数中,只有少数几种可以注入:提供者和常量.如果将一个服务注入进去,造成的结构就是在真正对其配置之前就将它实例化了

    config()的代码会按照顺序执行,可以定义在多个配置模块,通过这些模块我们可以自定义一些服务,比如权限List,Url以及API加密.


  运行块(run)

    和配置用的config不同,run作为运行块在注入器创建之后被执行,它是所有AngularJS应用中第一个被执行的方法.你可以将它当做一个main()方法,通常情况下,我会把一些隶属于整个App的,全局的东西放在这一部分.它和整个App高度耦合,例如全局的事件监听,路由的全选过滤等.

    之前说的每个路由的Url要通过Permission进行校验,这一操作就应该放在run()里面.

    最后附上修改过的预读取permission的代码:

(function(document,$,angular){  angular.element(document).ready(function() {
    $.ajax({
      url: '/api/get_user_permission',
      type: "GET",
      dataType: 'json'
    }).then(function(data){
        for (var i = 0; i < data.permissions.length; i++) {
          data.permissions[i] = data.permissions[i].replace(/\s/g,"");
        };
        angular.module('myApp').run(['$rootScope', function($rootScope){
          $rootScope = data.permissions;
        }]);
        angular.bootstrap(document, ['myApp']);
    });
  });
})(document,jQuery,angular);


展开阅读全文
打赏
0
2 收藏
分享
加载中
顽Shi博主

引用来自“令狐虫”的评论

用jquery加载初始化数据太丑陋了,用这个https://github.com/philippd/angular-deferred-bootstrap
=_=看起来不错
2015/03/13 10:34
回复
举报
用jquery加载初始化数据太丑陋了,用这个https://github.com/philippd/angular-deferred-bootstrap
2015/03/13 09:34
回复
举报
顽Shi博主

引用来自“男人天空别样蓝”的评论

能说下/api/get_user_permission 获取的是什么格式数据吗?
可以是一个permission的字符串数组,类似于:['permissionNameA','permissionNameB']这样,当然了,你也可以存到一个service里,比如CurrentUserService~方便在任何模块随时用.
2015/03/12 12:19
回复
举报
能说下/api/get_user_permission 获取的是什么格式数据吗?
2015/03/11 17:37
回复
举报
更多评论
打赏
4 评论
2 收藏
0
分享
返回顶部
顶部