通过路由依赖注入将angularjs应用拆分为多个组件
split angularjs application into components with routing dependency injection
对于给定的web应用程序-例如如果facebook-,我想分割成不同的模块
每个模块都只依赖于核心, 和不知道任何其他组件,所以在未来,如果我想添加或删除一个功能,我所要做的就是开发这个功能与它的html和js和指令里面的任何东西,只是添加依赖在核心模块和我很好去。
例如app将包含1. "path = "/components/Wall .js"2. 用户配置文件"/components/profile.js"3.聊天"/组件/chat.js"
都需要知道当前登录的用户详细信息,所以可能是核心模块将通过将用户详细信息暴露给$rootScope来处理这个问题。"/core.js "
那么整个应用用户必须登录才能访问,所以我将让core.js处理所有的身份验证
编辑以缩小问题范围
var core = angular.module("core", ['core.wall']);
var wall = angular.module("core.wall", []);
现在core 依赖 on wall,但在我的设计中,wall依赖于core。同时,核心路由被core改变。wall,因为wall应该声明自己的路由规则。
这个依赖注入是否可行?
所以我没有得到任何答案,但经过大量的玩耍,我想出了一个解决方案。
Angularjs模块的DI(依赖注入)的工作原理如下:
- 当你启动一个模块-自动使用
ng-app="module"
或手动触发angular.bootstrap(document,"module");
时,发生的第一件事是它的所有依赖项都被循环,所有的配置块都运行。
//我创建了一个github示例https://github.com/alzalabany/angular-material-modular-starter/
示例:
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.
因此,由于我们试图在本质上是模块化的。核心,因为我解释了我的问题应该依赖于没有其他app module
,但所有其他模块都依赖于它。为了做到这一点,我使用了一个中间模块,将它们连接在一起。
最终代码。-会尽快上传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. 我有$user信息可用于所有模块,2. 模块将它自己推到侧边栏,3.路由是在每个模块的配置块中声明的。4. 添加新模块我创建了一个新文件夹,添加链接到链接模块"zalabany在这个例子中"。我准备好了,验证和一切:-)
- React重新渲染但未显示正确的组件
- 不能从angular2中的子组件指定父组件中的数组
- 拨打'父亲'函数形式a'儿童'ReactJS中的组件
- React组件等待所需道具进行渲染
- 如何创建带有插槽的vue js组件预加载程序
- KnockoutJS-组件-多个实例
- 拆分单词jquery
- 如何更改reactjs中外部/独立组件的状态或属性
- 拆分文本以每隔n个字符添加一行新行,并注意空格
- 如何在react js中将值从一个组件发送到另一个组件
- React Native通过Navigator将用户输入数据传递到选项卡栏IOS中的组件
- React组件-设置页面标题
- 我的shareService在angular 2中发送值工作正常,但当我渲染我的另一个组件时,会获得默认值
- 如何在salesforce aura闪电组件中使用jQuery.val()
- 为react组件传递道具的最佳方式
- 如何将 react js 组件拆分为多个文件
- 使用webpack中的代码拆分在服务器端呈现组件
- 通过路由依赖注入将angularjs应用拆分为多个组件
- 为一个控制器拆分HTML组件会导致控制器停止工作
- 将react js组件拆分为单独的文件——并处理基于仪表板的应用程序的创建