ui-router $ stateParams与$ state.params


116

使用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
}

问题是,为什么会有区别?是否有关于何时何地应使用或避免使用它们的最佳实践指南?


如此出色地说明了问题-甚至感谢您告诉我我想问的问题!
彼得·尼克西

Answers:


65

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

如果我的记忆能发挥作用,$stateParams它的引入要晚于原始记忆$state.params,并且似乎是避免连续写入的简单辅助注入器$state.params

我怀疑是否有最佳实践准则,但是上下文对我而言是成功的。如果您只想访问URL中收到的参数,请使用$stateParams。如果您想了解有关状态本身的更复杂信息,请使用$state


1
我发现自己$state.params在中使用ACtrl,因为我想检查是否yetAnotherParam已设置。这样就可以了,我可以做点什么。我不打算进入的细节的东西,因为它可以保证它自己的问题。但是,我觉得我可能正在通过检查由子状态引入的参数和当前状态无法识别的参数来进行破解$stateParams。从那以后,我找到了另一种方法。
Merott

3
实际上,两者之间的差异不仅仅取决于上下文。$ stateParams捕获$ state认为适用于该状态的基于url的参数,即使其子状态包含更多params。$ state.params似乎捕获了您当前所在状态的所有url +基于非URL的参数。如果您处于state parent.child,则$stateParamsin parentController将评估的基于url的参数parent,但不评估parent.child。看到这个问题
Amy.js,2015年

1
另一方面,$ stateParams可以保留自定义对象,类型等,而$ state.params可以“将自定义对象转换为普通对象”。
Amy.js,2015年

2
$stateParams可以解决问题,但是$state.params不正确(未显示尚未解决的状态的参数)
karaxuna 2015年

1
我发现范围可以$ watch $ state.params,但不能$ stateParams。我不知道为什么。
weltschmerz 2015年

19

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

我只是在谷歌搜索如何传递状态而不必在URL中公开状态时发现了这一点,并在SO的其他地方回答了一个问题

基本上,它允许这种语法:

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

嗨,布朗,我不知何故不能使用它,您有一个可行的示例吗?
storm_buster 2014年

14

编辑:这个答案是正确的版本0.2.10。正如@Alexander Vasilyev指出的那样,它在version中不起作用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
}

2
不再适用。参见Plunker:plnkr.co/edit/r2JhV4PcYpKJdBCwHIWS?
Alexander Vasilyev

4

两者之间有许多差异。但是在实际工作时,我发现使用 $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'}
      }
    })

3

我有一个解决某事的根状态。传递$state为resolve参数不能保证的可用性$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:...}

使用“ angular”:“〜1.4.0”,“ angular-ui-router”:“〜0.2.15”


2

我在将先前的状态参数从一条路线传递到另一条路线时所做的有趣观察是,$ 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}}

1

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

因此,任何控制器都不应同时注入$state服务及其便利服务$stateParams。如果$state仅为了访问当前参数而注入,则应重写控制器以注入$stateParams

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.