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

Javascript 使用路由依赖注入将angularjs应用程序拆分为组件,javascript,angularjs,dependency-injection,module,circular-reference,Javascript,Angularjs,Dependency Injection,Module,Circular Reference,对于一个给定的webapp,例如facebook,我想把它分成不同的模块 每个模块只依赖于核心,,并且不知道任何其他组件——因此,将来如果我想添加或删除一个功能,我所要做的就是使用其html和js以及指令开发这个功能,只要在核心模块中添加依赖项,我就可以开始了 例如,应用程序将包含 1.wall“path=“/components/wall.js” 2.用户配置文件“/组件/profile.js” 3.chat“/组件/chat.js” 所有人都需要知道当前登录的用户详细信息,因此核心模块可能会

对于一个给定的webapp,例如facebook,我想把它分成不同的模块

每个模块只依赖于核心,并且不知道任何其他组件——因此,将来如果我想添加或删除一个功能,我所要做的就是使用其html和js以及指令开发这个功能,只要在核心模块中添加依赖项,我就可以开始了

例如,应用程序将包含 1.wall“path=“/components/wall.js” 2.用户配置文件“/组件/profile.js” 3.chat“/组件/chat.js”

所有人都需要知道当前登录的用户详细信息,因此核心模块可能会通过向$rootScope公开用户详细信息来处理此问题。“/core.js”

然后整个应用程序用户必须登录才能访问,所以我将让core.js处理所有身份验证

编辑以缩小问题范围

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

var wall = angular.module("core.wall", []);
现在核心依赖于墙,但在我的设计中,墙是依赖于核心的。但同时,核心路由由核心更改。墙因为墙应该声明自己的路由规则


这种依赖注入可行吗?

所以我没有得到任何答案,但在反复研究之后,我找到了一个解决方案

模块的AngularJSDI(依赖项注入)工作如下

  • 当您使用
    ng app=“module”
    自动引导模块时,或者通过触发
    angular.bootstrap(文档,“module”);
    手动引导模块时,首先发生的事情是它的所有依赖项都被循环,所有配置块都运行
  • //我创建了一个github示例

    例如:

    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.
    
    因此,由于我们试图在本质上实现模块化。正如我所解释的,我的问题的核心不应该依赖于任何其他的
    应用程序模块
    ,但所有其他模块都依赖于它。因此,为了实现这一点,我使用了一个中间模块,将它们连接在一起

    最终代码-将很快上传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
        });
    });
    
    从现在开始,向我的应用程序添加新组件非常简单

    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'});
    });
    
    这种结构的好处:- 1.i hv$用户信息适用于所有模块, 2.将模块自身推到侧栏, 3.路由在每个模块内部各自的配置块中声明。
    4.添加新模块i创建新文件夹,在本例中添加链接到链接模块“zalabany”“。关于身份验证和其他方面,我很乐意去做:-)

    这对StackOverflow来说是一个太宽泛的话题,你问了太多不同的问题。网上有很多关于棱角风格的指南,但归根结底,这些都取决于偏好。@AnidMonsur抱歉,我先是有点头脑风暴。我添加了一个小编辑,将问题总结为4行!这看起来很像,如果尝试的话很可能会返回一个错误。@Boaz没错,这就是为什么我标记了问题
    循环引用
    ,那么人们在这种情况下如何组织代码呢?这种方法和John Papa的热毛巾有很多相似之处,但他将每个模块都注入到主应用程序模块中。你也许可以通过看一看来获得一些见解。