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

116

Mit ui-routerist es möglich, entweder $stateoder $stateParamsin einen Controller zu injizieren , um Zugriff auf Parameter in der URL zu erhalten. Durch den Zugriff auf Parameter über werden jedoch $stateParamsnur Parameter verfügbar gemacht, die zu dem Status gehören, der von dem Controller verwaltet wird, der darauf zugreift, sowie zu den übergeordneten Status, während $state.paramsalle Parameter vorhanden sind, einschließlich derjenigen in allen untergeordneten Status.

Wenn wir mit dem folgenden Code die URL direkt laden http://path/1/paramA/paramB, geht das beim Laden der Controller folgendermaßen vor:

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

Die Frage ist, warum der Unterschied? Und gibt es Best Practices-Richtlinien, wann und warum Sie diese verwenden sollten, oder vermeiden Sie die Verwendung einer dieser Richtlinien?

Merott
quelle
Solch eine hervorragend illustrierte Frage - danke, dass Sie mir sogar erzählt haben, was ich zu fragen versuchte!
Peter Nixey

Antworten:

65

In der Dokumentation werden Ihre Ergebnisse hier wiederholt: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

Wenn mein Gedächtnis dient, $stateParamswurde es später als das Original eingeführt $state.paramsund scheint ein einfacher Hilfsinjektor zu sein, um ein kontinuierliches Schreiben zu vermeiden $state.params.

Ich bezweifle, dass es Best-Practice-Richtlinien gibt, aber der Kontext gewinnt für mich. Wenn Sie einfach auf die in der URL empfangenen Parameter zugreifen möchten, verwenden Sie $stateParams. Wenn Sie etwas Komplexeres über den Staat selbst wissen möchten, verwenden Sie $state.

Matt Way
quelle
1
Ich habe $state.paramsin verwendet ACtrl, weil ich überprüfen wollte, ob yetAnotherParameingestellt ist. Wenn es nicht so ist, kann ich etwas tun. Ich gehe nicht auf die Details dieses Etwas ein, da es eine eigene Frage rechtfertigen könnte. Ich habe jedoch das Gefühl, dass ich einen Hack mache, indem ich nach einem Parameter suche, der von einem untergeordneten Status eingeführt und vom aktuellen Status nicht erkannt wird $stateParams. Ich habe seitdem einen alternativen Ansatz gefunden.
Merott
3
Tatsächlich ist der Unterschied zwischen beiden mehr als nur eine Frage des Kontexts. $ stateParams erfasst URL-basierte Parameter, die nach Ansicht von $ state für diesen Status gelten, selbst wenn sein untergeordneter Status mehr Parameter enthält . $ state.params scheint alle URL + nicht URL-basierten Parameter des aktuellen Status zu erfassen, in dem Sie sich befinden. Wenn Sie sich im Status befinden parent.child, werden $stateParamsin parentControllerURL-basierte Parameter von ausgewertet parent, jedoch nicht die von parent.child. Siehe dieses Problem .
Amy.js
1
Andererseits kann $ stateParams benutzerdefinierte Objekte, Typen usw. beibehalten, während $ state.params "benutzerdefinierte Objekte in einfache Objekte konvertieren" würde.
Amy.js
2
$stateParamsfunktioniert in Auflösung, während $state.paramses falsch ist (zeigt keine Parameter für Zustand, der noch nicht gelöst ist)
Karaxuna
1
Ich habe festgestellt, dass der Bereich $ state.params $ beobachten kann, aber nicht $ stateParams. Ich habe keine Idee warum.
Weltschmerz
19

Ein weiterer Grund für die Verwendung $state.paramsist der nicht URL-basierte Status, der (meiner Meinung nach) völlig unterdokumentiert und sehr leistungsfähig ist.

Ich habe dies gerade entdeckt, als ich darüber gegoogelt habe, wie man den Status übergibt, ohne ihn in der URL offenlegen zu müssen, und eine Frage an anderer Stelle auf SO beantwortet .

Grundsätzlich erlaubt es diese Art von Syntax:

<a ui-sref="toState(thingy)" class="list-group-item" ng-repeat="thingy in thingies">{{ thingy.referer }}</a>
braun
quelle
Hallo bbrown, irgendwie kann ich es nicht zum Laufen bringen, hast du ein funktionierendes Beispiel?
Storm_Buster
14

EDIT: Diese Antwort ist für die Version korrekt 0.2.10. Wie @Alexander Vasilyev betonte, funktioniert es in der Version nicht 0.2.14.

Ein weiterer Grund für die Verwendung $state.paramsist, wenn Sie Abfrageparameter wie folgt extrahieren müssen:

$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
}
daerin
quelle
2
Nicht mehr anwendbar. Siehe Plunker: plnkr.co/edit/r2JhV4PcYpKJdBCwHIWS?p=preview
Alexander Vasilyev
4

Es gibt viele Unterschiede zwischen diesen beiden. Aber während ich praktisch arbeite, habe ich festgestellt, dass es $state.paramsbesser ist. Wenn Sie immer mehr Parameter verwenden, kann die Verwaltung verwirrend sein $stateParams. Wenn wir mehrere Parameter verwenden, die keine URL-Parameter sind, $stateist dies sehr nützlich

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

Ich habe einen Wurzelzustand, der etw auflöst. Die Übergabe $stateals Auflösungsparameter garantiert nicht die Verfügbarkeit für $state.params. Aber mit $stateParamsWillen.

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

Unter Verwendung von "Angular": "~ 1.4.0", "Angular-UI-Router": "~ 0.2.15"

jchnxu
quelle
2

Eine interessante Beobachtung, die ich beim Übergeben früherer Statusparameter von einer Route zur anderen gemacht habe, ist, dass $ stateParams angehoben wird und die Statusparameter der vorherigen Route überschreibt, die mit den aktuellen Statusparametern übergeben wurden, bei Verwendung von $state.params jedoch nicht.

Bei Verwendung von $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'}}

Bei Verwendung von $ 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}}
Shaun E. Tobias
quelle
1

Hier in diesem Artikel wird klar erklärt: Der $stateDienst bietet eine Reihe nützlicher Methoden zur Manipulation des Status sowie relevante Daten zum aktuellen Status. Auf die aktuellen $stateStatusparameter kann im Dienst über die Parametertaste zugegriffen werden. Der $stateParamsDienst gibt dasselbe Objekt zurück. Daher ist der $stateParamsDienst ausschließlich ein Komfortdienst, um schnell auf das params-Objekt im $stateDienst zuzugreifen .

Daher sollte kein Controller jemals sowohl den $stateDienst als auch seinen Komfortdienst einspeisen $stateParams. Wenn das $statenur injiziert wird, um auf die aktuellen Parameter zuzugreifen, sollte der Controller neu geschrieben werden, um $stateParamsstattdessen zu injizieren .

pabloRN
quelle