简体   繁体   English

使用路由依赖注入将 angularjs 应用程序拆分为组件

[英]split angularjs application into components with routing dependency injection

for a given webapp -for example if facebook- , i want to split into different modules对于给定的 webapp - 例如如果 facebook- ,我想分成不同的模块

each module are only depended on core , and unaware of anyother component -so that in future if i want to add or remove a feature all i have to do is develope this feature with its html and js and directives what ever inside it self, and just add dependency in core module and im good to go.每个模块只依赖于核心并且不知道任何其他组件 -所以将来如果我想添加或删除一个功能,我所要做的就是用它的 html 和 js 以及它内部的指令开发这个功能,并且只需在核心模块中添加依赖项,我就可以开始了。

for example app will contain 1. wall "path = "/components/wall.js" 2. user profile " /components/profile.js" 3. chat "/components/chat.js"例如应用程序将包含 1. wall "path = "/components/wall.js" 2. user profile " /components/profile.js" 3. chat "/components/chat.js"

all need to know current logged in user details, so may be the core module will handle this by exposing user details to $rootScope.所有人都需要知道当前登录的用户详细信息,因此核心模块可能会通过将用户详细信息暴露给 $rootScope 来处理此问题。 "/core.js" “/core.js”

then entire app user must be logged in to access, so i will let core.js handle all the authentication然后整个应用程序用户必须登录才能访问,所以我会让 core.js 处理所有身份验证

EDIT TO NARROW DOWN Question编辑缩小问题

var core = angular.module("core", ['core.wall']);

var wall = angular.module("core.wall", []);

Now core DEPENDE on wall, yet in my design , wall is the one that depends on core.现在核心依赖于墙,但在我的设计中,墙是依赖于核心的。 yet at same time, core routing is altered by core.wall since wall should declare its own routing rules.但同时,核心路由被 core.wall 改变,因为 wall 应该声明它自己的路由规则。

is this dependency injection doable ?这种依赖注入可行吗?

so i didnt get any answers but after lots of playing around i figured out a solution.所以我没有得到任何答案,但经过大量玩耍后,我想出了一个解决方案。

Angularjs DI (dependency injection) for modules works as follows.用于模块的 Angularjs DI(依赖注入)的工作原理如下。

  1. when you bootstrap a module -automatic using ng-app="module" or manually by triggering angular.bootstrap(document,"module");当您使用ng-app="module"或通过触发angular.bootstrap(document,"module");手动引导模块时angular.bootstrap(document,"module"); the first thing that happens is that all its dependencies are looped and all config blocks run.发生的第一件事是它的所有依赖项都被循环并且所有配置块都在运行。

//i created a github examplehttps://github.com/alzalabany/angular-material-modular-starter/ //我创建了一个 github 示例https://github.com/alzalabany/angular-material-modular-starter/

example :例子 :

angular.module('zalabany',['app.core','app.wall','app.blog']);
angular.bootstrap(document, ['zalabany']);
//1-->app.core config run, app.wall config run, app.blog config run, zalabany.config runs last
//2-->then .run blocks run in same order.

so since we are trying to be modular in nature.所以因为我们试图在本质上是模块化的。 the core as i explained my question should depend on no other app module yet all other modules depends on it.我解释我的问题的核心应该不依赖于其他app module但所有其他模块都依赖于它。 so to do this, i used an intermediate module, that link them together.为此,我使用了一个中间模块,将它们链接在一起。

Final code.最终代码。 -will upload git soon- -将很快上传git-

///Linking module, sole function is to connect all modules sharing same $rootScope and making sure system loads in correct order
angular.module('zalabany',['app.core','app.wall','app.blog']);

//I'm the Core.js i depend on external libs only. i'm not aware of my own system modules.
angular.module('app.core', ['ui.router', 'ngAnimate', 'toastr', 'ngMaterial','ngMdIcons'])
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
    ///http interceptor in case 403,401 on any request, redirect to login right away.
    $httpProvider.interceptors.push(function($q, $rootScope, $injector, $timeout, $window) {
        var toastr, $state, $http;
        //timeout is used to prevent circuler dependency error !
        $timeout(function() {
            toastr = $injector.get('toastr');
            $http = $injector.get('$http');
            $state = $injector.get('$state');
        });
        return {
            responseError: function(rejection) {
                if (rejection.data && rejection.data.hasOwnProperty('message')) {
                    toastr.error('request failed. try again later');
                }
                if (rejection.status === 401 || rejection.status === 403) {
                    console.log('rejected and redirecting', rejection);
                    $state.go('login');
                }
                return $q.reject(rejection);
            }
        };
    });

    $urlRouterProvider.otherwise("/login");

    $stateProvider
    .state('login', {
        url: "/login",
        templateUrl: "modules/core/login.html"
    });

    console.log('im config core');

})

.controller('loginCtrl', function($scope,$user,$rootScope){//remember $user is available every where
    var self=this;
    this.username = $user.username;


    if($user.token && $user.id){
        //validate token by sending get to auth.
        $http.defaults.headers.common["auth-token"] = $user.token;
        $http.defaults.headers.common["auth-uid"] = $user.id;

        $http.get($oauth).then(function(){$rootScope.Login($user);},$rootScope.Logout);

    }

    this.login= function(){
        $http.post($oauth,{username:self.username,password:self.password})
            .then(function(r){
                $rootScope.Login(r); //use login method on root to expose it for all modules
            });
    }
})

.run(function($rootScope, $state, $user,$http,$oauth) {
    ///$rootscope is shared between all modules. so i use it for sharing auth data since its just an object.
    $rootScope.$user = $user;

    $rootScope.$homepage = null;
    //default home page of appchild should overide it;
    //all children modules can edit this.


    ///FUNTION 1.
    ///LISTEN FOR ROUTE CHANGE AND PREVENT IF USER IS NOT LOGGED IN
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {

        if (!$rootScope.$user.hasOwnProperty('token') && toState.name !== 'login') {
            console.log('prevented');
            event.preventDefault();
            $state.go('login');
        }
    });


    $rootScope.Login = function(r){
    // login login ...
      $http.defaults.headers.common["auth-uid"] = r.token;
        angular.module('zalabany').value('$user',r);

        console.log('oki lets go hom',$state.go($rootScope.$homepage));
    }

    $rootScope.Logout = function(){
        window.localStorage.clear();
        $state.go('login');
    }

});


///BOOTSTRAP
$(function(){
    $.getJSON('PING API WITH TOKEN FROM LOCALSTORAGE', function(json) {
        $user = json || data;//json is our user record
    }).fail(function() {
        $user=data;
        window.localStorage.clear();
        console.log( "login error" );
    }).always(function() {
        angular.module('app.core')
                .value('$user',$user);
        angular.bootstrap(document, ['zalabany']); //bootstrap the link module
    });
});

from now on to adding new component to my app is as easy as从现在开始向我的应用程序添加新组件就像

angular.module('app.wall', ['app.core'])
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {

    $stateProvider
    .state('wall', {
        url: "/wall",
        templateUrl: "modules/wall/wall.html"
    });
})

.run(function($rootScope, $state, $user,$http,$oauth) {
    $rootScope.$homepage = 'wall';//Set homepage to me
    // or i can use
    $rootScope.$homepage = $rootScope.$homepage || 'wall';//set homepage to me if no other modules declared it it.

   //Push me into the sidebar.
   $rootScope.$sidebar.push({order:1, link:'/wall',title:'Feed',icon:'fa fa-star'});
});

Benefit of this structure :- 1. i hv $user info available for all modules, 2. module push it self to sidebar , 3. routes are declared inside each module in its own config block.这种结构的好处:- 1. i hv $user 信息可用于所有模块,2. 模块将其自我推送到侧边栏,3. 路由在每个模块内在其自己的配置块中声明。 4. adding new module i create new folder, add link to linking module "zalabany in this example". 4.添加新模块我创建新文件夹,添加链接到链接模块“本例中的zalabany”。 and i'm good to go, with authentication and everything :-)我很高兴,通过身份验证和一切:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM