`ui-router` $ stateParams กับ $ 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
}

คำถามคือทำไมความแตกต่าง? และมีแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับเวลาและเหตุผลที่คุณควรใช้หรือหลีกเลี่ยงการใช้อย่างใดอย่างหนึ่ง


เป็นคำถามที่มีภาพประกอบดีเยี่ยม - ขอบคุณที่บอกฉันแม้กระทั่งสิ่งที่ฉันพยายามจะถาม!
Peter Nixey

คำตอบ:


65

เอกสารนี้ย้ำการค้นพบของคุณที่นี่: https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service

หากหน่วยความจำของฉันทำหน้าที่$stateParamsเป็นที่รู้จักน้อยกว่าเดิมและน่าจะเป็นหัวฉีดช่วยที่ง่ายที่จะหลีกเลี่ยงการอย่างต่อเนื่องในการเขียน$state.params$state.params

ฉันสงสัยว่ามีแนวทางปฏิบัติที่ดีที่สุด แต่บริบทเป็นประโยชน์สำหรับฉัน หากคุณเพียงต้องการเข้าถึงพารามิเตอร์ที่ได้รับใน URL $stateParamsใช้แล้ว $stateหากคุณต้องการที่จะรู้ว่าบางสิ่งบางอย่างที่ซับซ้อนมากขึ้นเกี่ยวกับสถานะของตัวเองใช้


1
ฉันพบว่าตัวเองใช้$state.paramsในACtrlเพราะฉันต้องการตรวจสอบว่าyetAnotherParamตั้งค่าไว้หรือไม่ ดังนั้นถ้าไม่ใช่ฉันจะทำอะไรบางอย่างได้ ฉันจะไม่ลงรายละเอียดของสิ่งนั้นเพราะมันสามารถรับประกันคำถามของมันเองได้ แต่ผมรู้สึกว่าผมอาจจะทำสับ$stateParamsโดยการตรวจสอบสำหรับพารามิเตอร์ที่เป็นที่รู้จักโดยรัฐและเด็กไม่ได้รับการยอมรับจากรัฐในปัจจุบันผ่าน ฉันพบวิธีอื่นตั้งแต่นั้นมา
Merott

3
จริงๆแล้วความแตกต่างระหว่างทั้งสองเป็นมากกว่าเรื่องของบริบท $ stateParams จับพารามิเตอร์ตาม URL ที่ $ state พิจารณาว่าใช้กับสถานะนั้นแม้ว่าสถานะลูกจะมีพารามิเตอร์มากกว่าก็ตาม $ state.params ดูเหมือนว่าจะจับภาพทั้งหมด URL + ไม่ใช่ URL params ตามของรัฐในปัจจุบันคุณอยู่ใน. ถ้าคุณอยู่ในรัฐparent.childแล้ว$stateParamsในการparentControllerจะประเมิน params URL ตามแต่ไม่บรรดาparent parent.childดูปัญหานี้
Amy.js

1
ในทางกลับกัน $ stateParams สามารถเก็บรักษาออบเจ็กต์ที่กำหนดเองประเภท ฯลฯ ในขณะที่ $ state.params จะ "แปลงวัตถุที่กำหนดเองเป็นวัตถุธรรมดา"
Amy.js

2
$stateParamsทำงานในการแก้ไขในขณะที่$state.paramsไม่ถูกต้อง (ไม่แสดงพารามิเตอร์สำหรับสถานะที่ยังไม่ได้รับการแก้ไข)
karaxuna

1
ฉันพบว่าขอบเขตสามารถ $ watch $ state.params แต่ไม่ใช่ $ stateParams ฉันมีความคิดว่าทำไมไม่มี.
weltschmerz

19

อีกเหตุผลหนึ่งที่ต้องใช้$state.paramsคือสถานะที่ไม่อิง URL ซึ่ง (ในความคิดของฉัน) มีเอกสารไม่เพียงพอและมีประสิทธิภาพมาก

ฉันเพิ่งค้นพบสิ่งนี้ในขณะที่ googling เกี่ยวกับวิธีการผ่านสถานะโดยไม่ต้องเปิดเผยใน 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
Alexander Vasilyev

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

ฉันมีสถานะรูทที่แก้ไข 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"


2

ข้อสังเกตที่น่าสนใจที่ฉันทำในขณะที่ส่งพารามิเตอร์สถานะก่อนหน้าจากเส้นทางหนึ่งไปยังอีกเส้นทางหนึ่งคือ $ stateParams ถูกยกขึ้นและเขียนทับพารามิเตอร์สถานะของเส้นทางก่อนหน้าซึ่งถูกส่งผ่านด้วยพารามิเตอร์สถานะปัจจุบัน แต่ใช้ $state.param s ไม่ได้

เมื่อใช้$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บริการที่คีย์พารามิเตอร์ $stateParamsบริการส่งกลับวัตถุเดียวกันนี้มาก ดังนั้น$stateParamsบริการนี้จึงเป็นบริการอำนวยความสะดวกอย่างเคร่งครัดในการเข้าถึงวัตถุ params บนไฟล์$stateบริการอย่างรวดเร็ว

เช่นควบคุมไม่เคยควรฉีดทั้งบริการและการบริการที่สะดวกสบายของตน$state $stateParamsหาก$stateกำลังฉีดเพียงเพื่อเข้าถึงพารามิเตอร์ปัจจุบันตัวควบคุมควรจะเขียนใหม่เพื่อฉีด$stateParamsแทน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.