‘ ui-router’$stateParams vs $state.params

使用 ui-router,可以将 $state$stateParams注入到控制器中,以获得对 URL 中参数的访问。但是,通过 $stateParams访问参数只公开属于访问它的控制器管理的状态的参数及其父状态,而 $state.params具有所有参数,包括处于任何子状态的参数。

给定以下代码,如果我们直接加载 URL http://path/1/paramA/paramB,控制器加载时是这样的:

$stateProvider.state('a', {
url: 'path/:id/:anotherParam/',
controller: 'ACtrl',
});


$stateProvider.state('a.b', {
url: '/:yetAnotherParam',
controller: 'ABCtrl',
});


module.controller('ACtrl', function($stateParams, $state) {
$state.params; // has id, anotherParam, and yetAnotherParam
$stateParams;  // has id and anotherParam
}


module.controller('ABCtrl', function($stateParams, $state) {
$state.params; // has id, anotherParam, and yetAnotherParam
$stateParams;  // has id, anotherParam, and yetAnotherParam
}

问题是,为什么有区别?关于何时和为什么应该使用,或者避免使用其中任何一种,是否有最佳实践指南?

207079 次浏览

文档重申了你的发现: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

If my memory serves, $stateParams was introduced later than the original $state.params, and seems to be a simple helper injector to avoid continuously writing $state.params.

我怀疑是否有任何最佳实践指导方针,但是背景对我来说是最重要的。如果您只想访问 URL 中接收到的参数,那么可以使用 $stateParams。如果您想了解关于状态本身的更复杂的信息,请使用 $state

使用 $state.params的另一个原因是针对非基于 URL 的状态,(在我看来)这种状态文档不足,而且非常强大。

我刚刚发现这一点,而谷歌关于如何传递状态,而不必暴露它在 URL 和 在别处回答了一个问题上的所以。

基本上,它允许这样的语法:

<a ui-sref="toState(thingy)" class="list-group-item" ng-repeat="thingy in thingies">\{\{ thingy.referer }}</a>

编辑: 这个答案对于版本 0.2.10是正确的。正如@Alexander Vasilyev 指出的,它在版本 0.2.14中不起作用。

使用 $state.params的另一个原因是需要提取如下查询参数:

$stateProvider.state('a', {
url: 'path/:id/:anotherParam/?yetAnotherParam',
controller: 'ACtrl',
});


module.controller('ACtrl', function($stateParams, $state) {
$state.params; // has id, anotherParam, and yetAnotherParam
$stateParams;  // has id and anotherParam
}

这两者之间有许多不同之处。但在实际工作中,我发现使用 $state.params更好。当您使用越来越多的参数时,在 $stateParams中维护这些参数可能会造成混乱。在哪里,如果我们使用多个参数,而不是 URL 参数 $state是非常有用的

 .state('shopping-request', {
url: '/shopping-request/{cartId}',
data: {requireLogin: true},
params : {role: null},
views: {
'': {templateUrl: 'views/templates/main.tpl.html', controller: "ShoppingRequestCtrl"},
'body@shopping-request': {templateUrl: 'views/shops/shopping-request.html'},
'footer@shopping-request': {templateUrl: 'views/templates/footer.tpl.html'},
'header@shopping-request': {templateUrl: 'views/templates/header.tpl.html'}
}
})

我有一个能解决某事的根状态。将 $state作为解析参数传递并不能保证 $state.params的可用性。但使用 $stateParams可以。

var rootState = {
name: 'root',
url: '/:stubCompanyId',
abstract: true,
...
};


// case 1:
rootState.resolve = {
authInit: ['AuthenticationService', '$state', function (AuthenticationService, $state) {
console.log('rootState.resolve', $state.params);
return AuthenticationService.init($state.params);
}]
};
// output:
// rootState.resolve Object {}


// case 2:
rootState.resolve = {
authInit: ['AuthenticationService', '$stateParams', function (AuthenticationService, $stateParams) {
console.log('rootState.resolve', $stateParams);
return AuthenticationService.init($stateParams);
}]
};
// output:
// rootState.resolve Object {stubCompanyId:...}

使用“ angle”: “ ~ 1.4.0”,“ angle-ui-router”: “ ~ 0.2.15”

我在从一个路由传递前面的状态参数到另一个路由时发现了一个有趣的现象: $stateParams 被悬挂起来,并覆盖了前面路由的状态参数,这些状态参数是通过当前的状态参数传递的,但是使用 $state.params 却没有覆盖。

使用 $stateParams时:

var stateParams        = {};
stateParams.nextParams = $stateParams; //{item_id:123}
stateParams.next       = $state.current.name;


$state.go('app.login', stateParams);
//$stateParams.nextParams on app.login is now:
//{next:'app.details', nextParams:{next:'app.details'}}

使用 $state.params 时:

var stateParams        = {};
stateParams.nextParams = $state.params; //{item_id:123}
stateParams.next       = $state.current.name;


$state.go('app.login', stateParams);
//$stateParams.nextParams on app.login is now:
//{next:'app.details', nextParams:{item_id:123}}

本文中的 解释得很清楚: $state服务提供了许多有用的方法来操作状态以及当前状态的相关数据。在 $state服务上,可以通过 params 键访问当前状态参数。$stateParams服务返回这个相同的对象。因此,$stateParams服务严格来说是一种方便的服务,可以快速访问 $state服务上的 params 对象。

As such, no controller should ever inject both the $state service and its convenience service, $stateParams. If the $state is being injected just to access the current parameters, the controller should be rewritten to inject $stateParams instead.