`ui-router` $ stateParams vs. $ 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
}

Спрашивается, а в чем разница? И есть ли рекомендации по передовому опыту, когда и почему вам следует использовать или избегать использования любого из них?


Такой прекрасно иллюстрированный вопрос - спасибо, что сказали мне даже то, что я пытался задать!
Питер Никси

Ответы:


65

В документации повторяются ваши выводы здесь: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

Если мне не изменяет память, он $stateParamsбыл представлен позже оригинала $state.paramsи кажется простым вспомогательным инжектором, позволяющим избежать непрерывной записи $state.params.

Я сомневаюсь, что существуют какие-либо рекомендации по передовой практике, но для меня важен контекст. Если вам просто нужен доступ к параметрам, полученным в URL-адресе, используйте $stateParams. Если вы хотите узнать что-то более сложное о самом состоянии, используйте $state.


1
Я обнаружил, что использую $state.paramsin ACtrl, потому что хотел проверить, установлен ли yetAnotherParamон. Так что если это не так, я могу что-нибудь сделать. Я не буду вдаваться в подробности этого явления, поскольку это может вызвать самостоятельный вопрос. Однако я чувствую, что, возможно, делаю хакерство , проверяя параметр, который вводится дочерним состоянием и не распознается текущим состоянием через $stateParams. С тех пор я нашел альтернативный подход.
Merott

3
На самом деле разница между ними больше, чем просто контекст. $ stateParams фиксирует параметры на основе URL, которые, по мнению $ state, применяются к этому состоянию, даже если его дочернее состояние содержит больше параметров . $ state.params, похоже, захватывает все параметры, основанные на url + non-url текущего состояния, в котором вы находитесь. Если вы находитесь в состоянии parent.child, то $stateParamsin parentControllerбудет оценивать параметры на основе url parent, но не параметры parent.child. См. Эту проблему .
Amy.js

1
С другой стороны, $ stateParams может сохранять настраиваемые объекты, типы и т. Д., В то время как $ state.params «преобразовывает настраиваемые объекты в простые объекты».
Amy.js

2
$stateParamsработает в разрешении, а $state.paramsневерно (не отображаются параметры для состояния, которое еще не решено)
karaxuna

1
Я обнаружил, что область видимости может $ смотреть $ state.params, но не $ stateParams. Понятия не имею почему.
weltschmerz

19

Еще одна причина для использования $state.params- это состояние, не основанное на URL-адресах, которое (на мой взгляд) крайне недокументировано и очень мощно.

Я только что обнаружил это, когда гуглил о том, как передать состояние, не раскрывая его в URL-адресе, и ответил на вопрос в другом месте на SO.

По сути, он позволяет использовать такой синтаксис:

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

Привет, bbrown, как-то не получается заставить его работать, у тебя есть рабочий пример?
storm_buster

14

РЕДАКТИРОВАТЬ: этот ответ верен для версии 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
}

2
Больше не применимо. См. Plunker: plnkr.co/edit/r2JhV4PcYpKJdBCwHIWS?p=preview
Александр Васильев

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в качестве параметра разрешения не гарантирует доступность для $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Служба предоставляет ряд полезных методов для управления состоянием, а также соответствующие данные о текущем состоянии. Параметры текущего состояния доступны на $stateсервисе по ключу params. $stateParamsСлужба возвращает это тот же самый объект. Следовательно, эта $stateParamsслужба является исключительно удобной службой для быстрого доступа к объекту params на$state службе.

Таким образом , ни один контроллер никогда не должен вводить как $stateсервис и его обслуживание удобства $stateParams. Если $stateвводится только для доступа к текущим параметрам, $stateParamsвместо этого контроллер следует переписать на ввод .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.