`ui-router` $stateParams против $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
}

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

Ответ 1

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

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

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

Ответ 2

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

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

В принципе, он допускает такой синтаксис:

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

Ответ 3

EDIT: этот ответ верен для версии 0.2.10. Как отметил Александр Васильев, он не работает в версии 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
}

Ответ 4

У меня есть корневое состояние, которое разрешает sth. Передача $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"

Ответ 5

Есть много различий между этими двумя. Но, работая практически, я обнаружил, что лучше использовать $state.params. Когда вы используете все больше и больше параметров, это может запутать в $stateParams. где, если мы используем несколько параметров, которые не являются URL param $state, очень полезно

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

Ответ 6

Интересное наблюдение, которое я делал при передаче предыдущих параметров состояния от одного маршрута к другому, состоит в том, что $stateParams поднимается и перезаписывает предыдущие параметры состояния маршрута, которые были переданы с текущими параметрами состояния, но с использованием $state.param нет.

При использовании $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}}

Ответ 7

Здесь в этой статье ясно объяснено: служба $state предоставляет ряд полезных методов для управления состоянием, а также уместным данные о текущем состоянии. Текущие параметры состояния доступны в службе $state на ключ params. Служба $stateParams возвращает тот же самый объект. Следовательно, служба $stateParams является строго сервисным сервисом для быстрого доступа к объекту params в службе $state.

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