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


116

Dengan ui-router, dimungkinkan untuk menyuntikkan salah satu $stateatau $stateParamske pengontrol untuk mendapatkan akses ke parameter di URL. Namun, mengakses parameter melalui $stateParamshanya mengekspos parameter milik negara yang dikelola oleh pengontrol yang mengaksesnya, dan status induknya, sementara $state.paramsmemiliki semua parameter, termasuk yang ada di status turunan apa pun.

Diberikan kode berikut, jika kita langsung memuat URL http://path/1/paramA/paramB, begini jadinya ketika pengontrol memuat:

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

Pertanyaannya adalah, mengapa berbeda? Dan apakah ada pedoman praktik terbaik tentang kapan dan mengapa Anda harus menggunakan, atau menghindari penggunaan salah satunya?


Pertanyaan yang diilustrasikan dengan sangat baik - terima kasih telah memberi tahu saya bahkan apa yang ingin saya tanyakan!
Peter Nixey

Jawaban:


65

Dokumentasi mengulangi temuan Anda di sini: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

Jika ingatan saya berfungsi, $stateParamsdiperkenalkan lebih lambat dari aslinya $state.params, dan tampaknya menjadi injektor pembantu sederhana untuk menghindari terus menulis $state.params.

Saya ragu ada pedoman praktik terbaik, tetapi konteks menang bagi saya. Jika Anda hanya ingin akses ke params yang diterima ke dalam url, gunakan $stateParams. Jika Anda ingin mengetahui sesuatu yang lebih kompleks tentang negara bagian itu sendiri, gunakan $state.


1
Saya mendapati diri saya menggunakan $state.paramsin ACtrl, karena saya ingin memeriksa apakah yetAnotherParamsudah disetel. Jadi jika tidak, saya bisa melakukan sesuatu. Saya tidak akan menjelaskan secara rinci sesuatu itu karena hal itu dapat menjamin pertanyaannya sendiri. Namun, saya merasa saya mungkin melakukan peretasan dengan memeriksa parameter yang diperkenalkan oleh status anak dan tidak dikenali oleh status saat ini melalui $stateParams. Saya telah menemukan pendekatan alternatif sejak itu.
Merott

3
Sebenarnya perbedaan keduanya lebih dari sekedar masalah konteks. $ stateParams menangkap parameter berbasis url yang dianggap $ state berlaku untuk status tersebut, meskipun status turunannya berisi lebih banyak parameter . $ state.params tampaknya menangkap semua parameter berbasis url + non-url dari status Anda saat ini. Jika Anda dalam status parent.child, maka $stateParamsin parentControllerakan mengevaluasi parameter berbasis url parent, tetapi bukan parameter parent.child. Lihat masalah ini .
Amy.js

1
Di sisi lain, $ stateParams dapat mempertahankan objek khusus, tipe, dll. Sedangkan $ state.params akan "mengubah objek khusus menjadi objek biasa".
Amy.js

2
$stateParamsbekerja dalam penyelesaian, sementara $state.paramstidak benar (tidak menampilkan parameter untuk negara yang belum diselesaikan)
karaxuna

1
Saya menemukan bahwa scope bisa $ watch $ state.params, tapi tidak bisa $ stateParams. Saya tidak tahu kenapa.
weltschmerz

19

Alasan lain untuk menggunakan $state.paramsadalah untuk negara berbasis non-URL, yang (menurut saya) sangat kekurangan dokumen dan sangat kuat.

Saya baru saja menemukan ini saat mencari di Google tentang cara menyampaikan status tanpa harus mengeksposnya di URL dan menjawab pertanyaan di tempat lain di SO.

Pada dasarnya, ini memungkinkan sintaks semacam ini:

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

Hai bbrown, entah bagaimana saya tidak dapat membuatnya berfungsi, apakah Anda memiliki contoh yang berfungsi?
storm_buster

14

EDIT: Jawaban ini benar untuk versi 0.2.10. Seperti yang ditunjukkan @Alexander Vasilyev, ini tidak berfungsi dalam versi 0.2.14.

Alasan lain untuk menggunakan $state.paramsadalah saat Anda perlu mengekstrak parameter kueri seperti ini:

$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

Ada banyak perbedaan di antara keduanya. Tetapi saat bekerja secara praktis saya telah menemukan bahwa menggunakan $state.paramslebih baik. Saat Anda menggunakan lebih banyak parameter, ini mungkin membingungkan untuk dipertahankan $stateParams. dimana jika kita menggunakan beberapa param yang bukan $statemerupakan parameter URL sangat berguna

 .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

Saya memiliki status root yang menyelesaikan sth. Meneruskan $statesebagai parameter penyelesaian tidak akan menjamin ketersediaan untuk $state.params. Tapi menggunakan $stateParamskemauan.

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

Menggunakan "angular": "~ 1.4.0", "angular-ui-router": "~ 0.2.15"


2

Pengamatan menarik yang saya buat saat melewati parameter status sebelumnya dari satu rute ke rute lainnya adalah bahwa $ stateParams akan diangkat dan menimpa parameter status rute sebelumnya yang diteruskan dengan parameter status saat ini, tetapi menggunakan $state.params tidak.

Saat menggunakan $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'}}

Saat menggunakan $ 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

Di sini, di artikel ini dijelaskan dengan jelas: $stateLayanan menyediakan sejumlah metode yang berguna untuk memanipulasi status serta data terkait pada status saat ini. Parameter status saat ini dapat diakses pada $statelayanan di kunci params. The $stateParamslayanan mengembalikan objek yang sama ini. Oleh karena itu, $stateParamslayanan ini benar-benar merupakan layanan kenyamanan untuk mengakses objek params pada $statelayanan dengan cepat.

Dengan demikian, tidak ada pengontrol yang boleh menyuntikkan $statelayanan dan layanan kenyamanannya $stateParams,. Jika $statedisuntikkan hanya untuk mengakses parameter saat ini, pengontrol harus ditulis ulang untuk menyuntikkan $stateParamssebagai gantinya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.