web-dev-qa-db-fra.com

`ui-router` $ stateParams vs. $ state.params

Avec ui-router, il est possible d'injecter soit $state ou $stateParams dans un contrôleur pour accéder aux paramètres de l'URL. Cependant, l'accès aux paramètres via $stateParams expose uniquement les paramètres appartenant à l'état géré par le contrôleur qui y accède, ainsi que ses états parents, tandis que $state.params possède tous les paramètres, y compris ceux de tous les états enfants.

Étant donné le code suivant, si nous chargeons directement l'URL http://path/1/paramA/paramB, voici comment cela se passe lors du chargement des contrôleurs:

$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
}

La question est, pourquoi la différence? Et existe-t-il des directives sur les meilleures pratiques concernant le moment et la raison pour lesquels vous devriez utiliser ou éviter de les utiliser?

112
Merott

La documentation réitère vos conclusions ici: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

Si ma mémoire est bonne, $stateParams a été introduit plus tard que l'original $state.params, et semble être un simple injecteur auxiliaire pour éviter d'écrire en continu $state.params.

Je doute qu'il existe des lignes directrices sur les meilleures pratiques, mais le contexte l'emporte pour moi. Si vous souhaitez simplement accéder aux paramètres reçus dans l'URL, utilisez $stateParams. Si vous voulez savoir quelque chose de plus complexe à propos de l'état lui-même, utilisez $state.

62
Matt Way

Une autre raison d'utiliser $state.params est pour un état non basé sur une URL, ce qui (selon moi) est terriblement sous-documenté et très puissant.

Je viens de découvrir cela en cherchant sur Google comment passer d'un état à un autre sans avoir à l'exposer dans l'URL et répondu à une question ailleurs sur SO.

Fondamentalement, cela permet ce genre de syntaxe:

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

EDIT: Cette réponse est correcte pour la version 0.2.10. Comme @Alexander Vasilyev l'a souligné, cela ne fonctionne pas dans la version 0.2.14.

Une autre raison d'utiliser $state.params est lorsque vous devez extraire des paramètres de requête comme celui-ci:

$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
}
14
daerin

Il y a beaucoup de différences entre ces deux. Mais en travaillant, j’ai constaté que mieux utiliser $state.params. Lorsque vous utilisez de plus en plus de paramètres, la maintenance dans $stateParams peut être compliquée. où si nous utilisons plusieurs paramètres qui ne sont pas des URL, le paramètre $state est très utile

 .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'}
      }
    })
4
Abdullah Al Noman

J'ai un état racine qui résout qc. Le fait de passer $state en tant que paramètre de résolution ne garantit pas la disponibilité de $state.params. Mais en utilisant $stateParams sera.

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:...}

Utilisation de "angular": "~ 1.4.0", "angular-ui-router": "~ 0.2.15"

3
jchnxu

Une observation intéressante que j'ai faite lors du passage des paramètres d'état précédents d'une route à une autre est que $ stateParams est levé et écrase les paramètres d'état de la route précédente qui ont été transmis avec les paramètres d'état actuels, mais pas $state.params.

Lorsque vous utilisez $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'}}

Lorsque vous utilisez $ 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}}
2
Shaun Tobias

Ici dans cet article est clairement expliqué: Le service $state fournit un certain nombre de méthodes utiles pour manipuler l'état ainsi que des données pertinentes sur l'état actuel. Les paramètres d'état en cours sont accessibles sur le service $state à la touche params. Le service $stateParams renvoie ce même objet. Par conséquent, le service $stateParams est strictement un service de commodité permettant d’accéder rapidement à l’objet params du service $state.

En tant que tel, aucun contrôleur ne doit jamais injecter à la fois le service $state et son service de proximité, $stateParams. Si le $state est injecté uniquement pour accéder aux paramètres actuels, le contrôleur doit être réécrit pour injecter $stateParams à la place.

1
pabloRN