AngularJS ui-路由器:如何全局解析所有路由的典型数据?
AngularJS ui-router: how to resolve typical data globally for all routes?
我有一个 AngularJS 与服务器通信的服务和 returns
应用程序不同部分的翻译:
angular
.module('utils')
.service('Translations', ['$q','$http',function($q, $http) {
translationsService = {
get: function(section) {
if (!promise) {
var q = $q.defer();
promise = $http
.get(
'/api/translations',
{
section: section
})
.success(function(data,status,headers,config) {
q.resolve(result.data);
})
.error(function(data,status,headers,config){
q.reject(status);
});
return q.promise;
}
}
};
return translationsService;
}]);
该部分的名称作为 section
函数的 get
参数传递。
我正在使用 AngularJS ui-router 模块并遵循描述的设计模式 here
所以我有以下状态配置:
angular.module('app')
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('users', {
url: '/users',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('users');
}
]
},
templateUrl: '/app/users/list.html',
controller: 'usersController',
controllerAs: 'vm'
})
.state('shifts', {
url: '/shifts',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('shifts');
}
]
},
templateUrl: '/app/shifts/list.html',
controller: 'shiftsController',
controllerAs: 'vm'
})
这很好用,但您可能会注意到我必须在 resolve 参数中明确指定 translations
。我认为这还不够好,因为这会重复逻辑。
有什么办法可以全局解析翻译,避免代码重复。我的意思是某种中间件。
我正在考虑监听 $stateChangeStart
,然后获取特定于新状态的翻译并将它们绑定到控制器,但我还没有找到实现它的方法。
任何建议将不胜感激。
重要提示:
在我的例子中,解析的 translations object
必须包含翻译数据,而不是 service/factory/whatever.
亲切的问候。
让我告诉你我的方法。还有is a working plunker
让我们有一个像这样的translation.json
:
{
"home" : "trans for home",
"parent" : "trans for parent",
"parent.child" : "trans for child"
}
下面介绍超parent状态root
$stateProvider
.state('root', {
abstract: true,
template: '<div ui-view=""></div>',
resolve: ['Translations'
, function(Translations){return Translations.loadAll();}]
});
这个超级根状态没有任何url
(不影响任何child url)。现在,我们将默默地将其注入每个状态:
$stateProvider
.state('home', {
parent: 'root',
url: "/home",
templateUrl: 'tpl.html',
})
.state('parent', {
parent: 'root',
url: "/parent",
templateUrl: 'tpl.html',
})
如我们所见,我们使用设置 parent
- 而不是 effect/extend 原始状态 name.
根状态正在通过新方法一次性加载翻译 loadAll()
:
.service('Translations', ['$http'
,function($http) {
translationsService = {
data : {},
loadAll : function(){
return $http
.get("translations.json")
.then(function(response){
this.data = response.data;
return this.data;
})
},
get: function(section) {
return data[section];
}
};
return translationsService;
}])
我们根本不需要$q
。我们的超级根状态只解决了一次......通过 $http
和 loadAll()
方法。现在所有这些都已加载,我们甚至可以将该服务放入 $rootScope
:
.run(['$rootScope', '$state', '$stateParams', 'Translations',
function ($rootScope, $state, $stateParams, Translations) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.Translations = Translations;
}])
我们可以像这样访问它:
<h5>Translation</h5>
<pre>{{Translations.get($state.current.name) | json}}</pre>
哇...这是几乎从 UI-Router 附带的每个功能中获利的解决方案...我会说。全部加载一次。由于 $rootScope 和视图继承而全部继承...在任何 child 状态下都可用...
检查所有 here.
虽然这是一个很老的问题,但我想 post 我现在正在使用的解决方案。希望它将来对某人有所帮助。
在使用了一些不同的方法后,我想出了一个 beautiful angularjs pattern by John Papa
他建议使用特殊服务 routerHelperProvider
并将状态配置为常规 JS 对象。我不打算在这里复制粘贴整个提供程序。有关详细信息,请参阅上面的 link。但我将展示我是如何通过该服务解决我的问题的。
这是该提供程序的代码部分,它获取 JS 对象并将其转换为状态配置:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
$stateProvider.state(state.state, state.config);
});
我改造如下:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
var resolveAlways = {
translations: ['Translations', function(Translations) {
if (state.translationCategory) {
return Translations.get(state.translationCategory);
} else {
return {};
}
}],
};
state.config.resolve =
angular.extend(state.config.resolve || {}, resolveAlways || {});
$stateProvider.state(state.state, state.config);
});
});
我的路由配置对象现在如下所示:
{
state: ‘users’,
translationsCategory: ‘users’,
config: {
controller: ‘usersController’
controllerAs: ‘vm’,
url: ‘/users’.
templateUrl: ‘users.html'
}
所以我做了什么:
我实现了 resolveAlways
对象,它采用自定义 translationsCategory
属性,注入 Translations
服务并解析必要的数据。现在不需要每次都这样做了。
我有一个 AngularJS 与服务器通信的服务和 returns 应用程序不同部分的翻译:
angular
.module('utils')
.service('Translations', ['$q','$http',function($q, $http) {
translationsService = {
get: function(section) {
if (!promise) {
var q = $q.defer();
promise = $http
.get(
'/api/translations',
{
section: section
})
.success(function(data,status,headers,config) {
q.resolve(result.data);
})
.error(function(data,status,headers,config){
q.reject(status);
});
return q.promise;
}
}
};
return translationsService;
}]);
该部分的名称作为 section
函数的 get
参数传递。
我正在使用 AngularJS ui-router 模块并遵循描述的设计模式 here
所以我有以下状态配置:
angular.module('app')
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('users', {
url: '/users',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('users');
}
]
},
templateUrl: '/app/users/list.html',
controller: 'usersController',
controllerAs: 'vm'
})
.state('shifts', {
url: '/shifts',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('shifts');
}
]
},
templateUrl: '/app/shifts/list.html',
controller: 'shiftsController',
controllerAs: 'vm'
})
这很好用,但您可能会注意到我必须在 resolve 参数中明确指定 translations
。我认为这还不够好,因为这会重复逻辑。
有什么办法可以全局解析翻译,避免代码重复。我的意思是某种中间件。
我正在考虑监听 $stateChangeStart
,然后获取特定于新状态的翻译并将它们绑定到控制器,但我还没有找到实现它的方法。
任何建议将不胜感激。
重要提示:
在我的例子中,解析的 translations object
必须包含翻译数据,而不是 service/factory/whatever.
亲切的问候。
让我告诉你我的方法。还有is a working plunker
让我们有一个像这样的translation.json
:
{
"home" : "trans for home",
"parent" : "trans for parent",
"parent.child" : "trans for child"
}
下面介绍超parent状态root
$stateProvider
.state('root', {
abstract: true,
template: '<div ui-view=""></div>',
resolve: ['Translations'
, function(Translations){return Translations.loadAll();}]
});
这个超级根状态没有任何url
(不影响任何child url)。现在,我们将默默地将其注入每个状态:
$stateProvider
.state('home', {
parent: 'root',
url: "/home",
templateUrl: 'tpl.html',
})
.state('parent', {
parent: 'root',
url: "/parent",
templateUrl: 'tpl.html',
})
如我们所见,我们使用设置 parent
- 而不是 effect/extend 原始状态 name.
根状态正在通过新方法一次性加载翻译 loadAll()
:
.service('Translations', ['$http'
,function($http) {
translationsService = {
data : {},
loadAll : function(){
return $http
.get("translations.json")
.then(function(response){
this.data = response.data;
return this.data;
})
},
get: function(section) {
return data[section];
}
};
return translationsService;
}])
我们根本不需要$q
。我们的超级根状态只解决了一次......通过 $http
和 loadAll()
方法。现在所有这些都已加载,我们甚至可以将该服务放入 $rootScope
:
.run(['$rootScope', '$state', '$stateParams', 'Translations',
function ($rootScope, $state, $stateParams, Translations) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.Translations = Translations;
}])
我们可以像这样访问它:
<h5>Translation</h5>
<pre>{{Translations.get($state.current.name) | json}}</pre>
哇...这是几乎从 UI-Router 附带的每个功能中获利的解决方案...我会说。全部加载一次。由于 $rootScope 和视图继承而全部继承...在任何 child 状态下都可用...
检查所有 here.
虽然这是一个很老的问题,但我想 post 我现在正在使用的解决方案。希望它将来对某人有所帮助。 在使用了一些不同的方法后,我想出了一个 beautiful angularjs pattern by John Papa
他建议使用特殊服务 routerHelperProvider
并将状态配置为常规 JS 对象。我不打算在这里复制粘贴整个提供程序。有关详细信息,请参阅上面的 link。但我将展示我是如何通过该服务解决我的问题的。
这是该提供程序的代码部分,它获取 JS 对象并将其转换为状态配置:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
$stateProvider.state(state.state, state.config);
});
我改造如下:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
var resolveAlways = {
translations: ['Translations', function(Translations) {
if (state.translationCategory) {
return Translations.get(state.translationCategory);
} else {
return {};
}
}],
};
state.config.resolve =
angular.extend(state.config.resolve || {}, resolveAlways || {});
$stateProvider.state(state.state, state.config);
});
});
我的路由配置对象现在如下所示:
{
state: ‘users’,
translationsCategory: ‘users’,
config: {
controller: ‘usersController’
controllerAs: ‘vm’,
url: ‘/users’.
templateUrl: ‘users.html'
}
所以我做了什么:
我实现了 resolveAlways
对象,它采用自定义 translationsCategory
属性,注入 Translations
服务并解析必要的数据。现在不需要每次都这样做了。