`ui-router` $ stateParams so với $ state.params


116

Với ui-router, có thể tiêm một $statehoặc $stateParamsvào bộ điều khiển để có quyền truy cập vào các tham số trong URL. Tuy nhiên, việc truy cập các tham số thông qua $stateParamschỉ hiển thị các tham số thuộc trạng thái được quản lý bởi bộ điều khiển truy cập vào nó và trạng thái cha của nó, trong khi $state.paramscó tất cả các tham số, bao gồm cả các tham số ở bất kỳ trạng thái con nào.

Đưa ra đoạn mã sau, nếu chúng tôi tải trực tiếp URL http://path/1/paramA/paramB, đây là cách nó diễn ra khi bộ điều khiển tải:

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

Câu hỏi là, tại sao sự khác biệt? Và có những hướng dẫn thực hành tốt nhất xung quanh khi nào và tại sao bạn nên sử dụng, hoặc tránh sử dụng một trong số chúng?


Một câu hỏi minh họa xuất sắc như vậy - cảm ơn bạn đã cho tôi biết ngay cả những gì tôi đang cố gắng hỏi!
Peter Nixey

Câu trả lời:


65

Tài liệu nhắc lại những phát hiện của bạn tại đây: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

Nếu bộ nhớ của tôi phục vụ, $stateParamsđược giới thiệu muộn hơn so với bản gốc $state.paramsvà dường như là một trình trợ giúp đơn giản để tránh viết liên tục $state.params.

Tôi nghi ngờ có bất kỳ hướng dẫn thực hành tốt nhất, nhưng bối cảnh chiến thắng cho tôi. Nếu bạn chỉ muốn truy cập vào các thông số nhận được vào url, thì hãy sử dụng $stateParams. Nếu bạn muốn biết một cái gì đó phức tạp hơn về chính trạng thái, hãy sử dụng $state.


1
Tôi thấy mình sử dụng $state.paramstrong ACtrl, bởi vì tôi muốn kiểm tra nếu yetAnotherParamđược thiết lập. Vì vậy, nếu không, tôi có thể làm một cái gì đó. Tôi sẽ không đi sâu vào chi tiết về điều gì đó vì nó có thể đảm bảo một câu hỏi của riêng nó. Tuy nhiên, tôi cảm thấy mình có thể thực hiện hack bằng cách kiểm tra tham số được giới thiệu bởi trạng thái con và không được trạng thái hiện tại nhận ra $stateParams. Tôi đã tìm thấy một cách tiếp cận khác kể từ đó.
Merott

3
Trên thực tế, sự khác biệt giữa hai không chỉ là vấn đề bối cảnh. $ stateParams nắm bắt các thông số dựa trên url mà $ state xem xét áp dụng cho trạng thái đó, ngay cả khi trạng thái con của nó chứa nhiều thông số hơn . $ state.params dường như nắm bắt tất cả url + phi url params dựa của nhà nước hiện tại bạn đang ở trong. Nếu bạn đang ở trong trạng thái parent.child, sau đó $stateParamstrong parentControllersẽ đánh giá params url dựa trên parent, nhưng không phải những người parent.child. Xem vấn đề này .
Amy.js 30/03/2015

1
Mặt khác, $ stateParams có thể bảo tồn các đối tượng tùy chỉnh, loại, v.v. trong khi $ state.params sẽ "chuyển đổi các đối tượng tùy chỉnh thành các đối tượng đơn giản".
Amy.js 30/03/2015

2
$stateParamshoạt động trong giải quyết, trong khi $state.paramskhông chính xác (không hiển thị thông số cho trạng thái chưa được giải quyết)
karaxuna

1
Tôi thấy rằng phạm vi có thể $ xem $ state.params, nhưng không phải $ stateParams. Tôi không biết tại sao.
Weltschmerz

19

Một lý do khác để sử dụng $state.paramslà cho trạng thái không dựa trên URL, mà (theo suy nghĩ của tôi) được đánh giá thấp và rất mạnh mẽ.

Tôi vừa phát hiện ra điều này trong khi googling về cách vượt qua trạng thái mà không phải phơi bày nó trong URL và trả lời một câu hỏi khác trên SO.

Về cơ bản, nó cho phép loại cú pháp này:

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

Chào bbrown, bằng cách nào đó tôi không thể làm cho nó hoạt động, bạn có một ví dụ làm việc không?
bão_buster

14

EDIT: Câu trả lời này là chính xác cho phiên bản 0.2.10. Như @Alexander Vasilyev đã chỉ ra rằng nó không hoạt động trong phiên bản 0.2.14.

Một lý do khác để sử dụng $state.paramslà khi bạn cần trích xuất các tham số truy vấn như thế này:

$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
Không áp dụng nữa. Xem Plunker: plnkr.co/edit/r2JhV4PcYpKJdBCwHIWS?p=preview
Alexander Vasilyev

4

Có nhiều sự khác biệt giữa hai điều này. Nhưng trong khi làm việc thực tế tôi đã thấy rằng sử dụng $state.paramstốt hơn. Khi bạn sử dụng càng nhiều tham số thì điều này có thể gây nhầm lẫn để duy trì $stateParams. trong đó nếu chúng ta sử dụng nhiều thông số không phải là thông số URL $statethì rất hữu ích

 .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

Tôi có một trạng thái gốc mà giải quyết sth. Truyền $statedưới dạng tham số giải quyết sẽ không đảm bảo tính khả dụng cho $state.params. Nhưng sử dụng $stateParamsý chí.

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

Sử dụng "angular": "~ 1.4.0", "angular-ui-router": "~ 0.2.15"


2

Một quan sát thú vị mà tôi đã thực hiện trong khi chuyển các thông số trạng thái trước đó từ tuyến này sang tuyến khác là $ stateParams được nâng lên và ghi đè lên các thông số trạng thái của tuyến trước được truyền với thông số trạng thái hiện tại, nhưng sử dụng $state.paramthì không.

Khi sử dụng $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'}}

Khi sử dụng $ 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

Ở đây trong bài viết này được giải thích rõ ràng: $stateDịch vụ cung cấp một số phương pháp hữu ích để thao túng trạng thái cũng như dữ liệu thích hợp về trạng thái hiện tại. Các tham số trạng thái hiện tại có thể truy cập được trên $statedịch vụ tại phím params. Các $stateParamsdịch vụ trả về đối tượng này rất giống nhau. Do đó, $stateParamsdịch vụ hoàn toàn là một dịch vụ tiện lợi để nhanh chóng truy cập vào đối tượng params trên $statedịch vụ.

Như vậy, không có bộ điều khiển nào nên tiêm cả $statedịch vụ và dịch vụ tiện lợi của nó , $stateParams. Nếu $stateđang được tiêm chỉ để truy cập các tham số hiện tại, bộ điều khiển nên được viết lại để tiêm $stateParamsthay thế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.