การกำหนดเส้นทางด้วยพารามิเตอร์ใน AngularJs
⚡ สรุปอย่างชาญฉลาด
การกำหนดเส้นทางใน AngularJS เปลี่ยนหน้า HTML หน้าเดียวให้กลายเป็นแอปพลิเคชันที่มีหลายมุมมองโดยใช้แผนที่ping URL แปลงส่วนย่อยเป็นเทมเพลตและคอนโทรลเลอร์ โมดูล ngRoute และบริการ $routeProvider กำหนดการแมปเหล่านี้pingในขณะที่คำสั่ง ng-view จะแทรกเทมเพลตที่ตรงกันเข้าไป

ก่อนที่เราจะไปดูวิธีการทำงานของการกำหนดเส้นทางใน AngularJS เราควรทำความเข้าใจก่อนว่าการกำหนดเส้นทางนั้นถูกสร้างขึ้นมาเพื่อแอปพลิเคชันประเภทใด ส่วนด้านล่างนี้จะอธิบายบริบทนั้น และทุกเทคนิคที่จะตามมาจะสร้างขึ้นบนพื้นฐานนั้น
แอปพลิเคชันหน้าเดียวคืออะไร
แอปพลิเคชันหน้าเดียว หรือ SPA (Single Page Application) คือแอปพลิเคชันบนเว็บที่โหลดหน้า HTML เพียงหน้าเดียว แล้วอัปเดตหน้านั้นแบบไดนามิกเมื่อผู้ใช้โต้ตอบกับมัน แทนที่จะขอเอกสารใหม่จากเซิร์ฟเวอร์ทุกครั้งที่คลิก SPA จะเปลี่ยนเฉพาะส่วนของหน้าที่เปลี่ยนแปลงเท่านั้น
การออกแบบเช่นนั้นก่อให้เกิดปัญหาอย่างหนึ่ง หากเบราว์เซอร์ไม่เคยไปยังเอกสารใหม่ แถบที่อยู่ก็จะไม่เปลี่ยนแปลง ทำให้ผู้ใช้ไม่สามารถคั่นหน้าหน้าจอ แชร์ หรือใช้ปุ่มย้อนกลับได้ การกำหนดเส้นทาง (Routing) ช่วยแก้ปัญหานี้ได้อย่างลงตัว
การกำหนดเส้นทางใน AngularJS คืออะไร
การกำหนดเส้นทางใน AngularJS เป็นวิธีการที่ช่วยให้คุณสร้างแอปพลิเคชันหน้าเดียว (Single Page Application) ได้ โดยจะช่วยให้คุณสร้างสิ่งต่างๆ ได้หลากหลาย URLการกำหนดเส้นทาง (routing) ใน AngularJS ช่วยให้แสดงเนื้อหาได้หลากหลายขึ้นอยู่กับเส้นทางที่เลือก โดยจะระบุไว้ในไฟล์ .ng/ ... URL หลังเครื่องหมาย #
ลองยกตัวอย่างเว็บไซต์ที่โฮสต์ผ่านทาง... URL http://example.com/index.html.
หน้านี้คือหน้าจอหลักของแอปพลิเคชันของคุณ สมมติว่าแอปพลิเคชันนี้ใช้จัดการกิจกรรม และผู้ใช้ต้องการแสดงรายการกิจกรรม ดูรายละเอียด หรือลบกิจกรรม ในแอปพลิเคชันแบบหน้าเดียว (Single Page Application) ที่เปิดใช้งานการกำหนดเส้นทาง (Routing) ฟังก์ชันทั้งหมดนี้สามารถเข้าถึงได้ผ่านลิงก์ต่อไปนี้
สัญลักษณ์ # จะถูกใช้พร้อมกับเส้นทางที่แตกต่างกัน (ShowEvent, DisplayEvent และ DeleteEvent)
- หากต้องการดูเหตุการณ์ทั้งหมด ผู้ใช้จะถูกนำไปยัง http://example.com/index.html#ShowEvent
- หากต้องการชมเหตุการณ์ใดเหตุการณ์หนึ่งโดยเฉพาะ พวกเขาจะถูกแนะนำให้ไปที่... http://example.com/index.html#DisplayEvent
- หากต้องการลบกิจกรรม พวกเขาจะถูกนำไปยัง... http://example.com/index.html#DeleteEvent
โปรดทราบว่าหลัก URL ยังคงเหมือนเดิม มีเพียงส่วนหลังเครื่องหมาย # เท่านั้นที่เปลี่ยนแปลง และส่วนนั้นคือสิ่งที่ AngularJS คอยตรวจสอบ เมื่อเข้าใจแนวคิดนี้แล้ว ส่วนถัดไปจะกล่าวถึงส่วนประกอบต่างๆ ที่คุณต้องเชื่อมต่อเข้าด้วยกันก่อนที่ทุกอย่างจะใช้งานได้
การเพิ่มเส้นทาง AngularJS โดยใช้ $routeProvider
ดังที่ได้กล่าวไว้ก่อนหน้านี้ เส้นทางใน AngularJS ใช้เพื่อนำผู้ใช้ไปยังมุมมองอื่นของแอปพลิเคชันของคุณ การกำหนดเส้นทางนี้ทำบนหน้า HTML เดียวกัน ดังนั้นผู้ใช้จึงรู้สึกเหมือนไม่ได้ออกจากหน้าเว็บ
ในการนำระบบการกำหนดเส้นทางมาใช้ จะต้องดำเนินการตามขั้นตอนหลักต่อไปนี้ในแอปพลิเคชันของคุณ โดยไม่จำเป็นต้องเรียงลำดับตามต้องการ
- อ้างอิงถึงไฟล์ angular-route.js นี้ Javaต้นฉบับ ไฟล์ที่พัฒนาโดย Googleประกอบด้วยฟังก์ชันการกำหนดเส้นทางทั้งหมด และต้องรวมไว้เพื่อให้แอปพลิเคชันสามารถอ้างอิงถึงความต้องการการกำหนดเส้นทางของโมดูลได้
- เพิ่ม dependency ไปยังโมดูล ngRoute จากภายในแอปพลิเคชันของคุณ หากไม่มี dependency นี้ จะไม่สามารถใช้งานการกำหนดเส้นทาง (routing) ในแอปพลิเคชัน AngularJS ได้เลย
ด้านล่างนี้คือไวยากรณ์ทั่วไปของคำสั่งนี้ นี่เป็นเพียงการประกาศปกติของโมดูลที่มีการรวมคีย์เวิร์ด ngRoute
var module = angular.module("sampleApp", ['ngRoute']);
- กำหนดค่าตัวแปร `$routeProvider` ของคุณ ตัวแปรนี้จะกำหนดเส้นทางต่างๆ ในแอปพลิเคชันของคุณ โดยไวยากรณ์จะระบุว่า เมื่อเลือกเส้นทางที่เกี่ยวข้องแล้ว ให้ใช้เส้นทางนั้นในการแสดงผลมุมมองที่กำหนด
when(path, route)
- ลิงก์ไปยังเส้นทางของคุณจากภายในหน้า HTML ของคุณ ในหน้า HTML คุณจะเพิ่มลิงก์อ้างอิงไปยังเส้นทางต่างๆ ที่มีอยู่ในแอปพลิเคชันของคุณ
<a href="#!/route1">Route 1</a><br/>
- ในที่สุดก็จะรวมของ คำสั่ง ng-viewซึ่งโดยปกติจะอยู่ในแท็ก div สิ่งนี้จะถูกใช้เพื่อแทรกเนื้อหาของมุมมองเมื่อเลือกเส้นทางที่เกี่ยวข้อง
💡 เคล็ดลับ: ทั้งห้าขั้นตอนเป็นขั้นตอนบังคับ สาเหตุที่พบบ่อยที่สุดที่ทำให้เส้นทาง (route) ไม่ทำงานโดยไม่มีการแจ้งเตือนใดๆ คือการขาดการอ้างอิง angular-route.js เนื่องจาก $routeProvider จะไม่มีอยู่หากไม่มีการอ้างอิงดังกล่าว ส่วนถัดไปจะนำทั้งห้าขั้นตอนมารวมกันในตัวอย่างการทำงาน
ตัวอย่างการกำหนดเส้นทาง AngularJS
ตอนนี้เรามาดูตัวอย่างการกำหนดเส้นทางโดยใช้ขั้นตอนที่กล่าวมาข้างต้น
ในตัวอย่างการกำหนดเส้นทาง AngularJS ของเราพร้อมพารามิเตอร์
- ลิงก์หนึ่งใช้สำหรับแสดงหัวข้อต่างๆ AngularJS แน่นอนและอีกอันหนึ่งมีไว้สำหรับ Node.js หลักสูตร
- เมื่อผู้ใช้คลิกลิงก์ใดลิงก์หนึ่ง หัวข้อสำหรับหลักสูตรนั้นจะปรากฏขึ้น
ขั้นตอน 1) รวมไฟล์เชิงมุมเป็นการอ้างอิงสคริปต์
ไฟล์กำหนดเส้นทางนี้จำเป็นสำหรับการใช้งานฟังก์ชันการมีเส้นทางและมุมมองหลายรายการ ไฟล์นี้สามารถดาวน์โหลดได้บนเว็บไซต์ AngularJS
ขั้นตอน 2) เพิ่มแท็ก href ซึ่งจะแสดงลิงก์ไปยัง “หัวข้อ JS เชิงมุม” และ “หัวข้อ JS ของโหนด”
ขั้นตอน 3) เพิ่มแท็ก div ด้วยคำสั่ง ng-view ซึ่งจะแสดงมุมมอง
สิ่งนี้จะช่วยให้สามารถแทรกมุมมองที่เกี่ยวข้องเมื่อใดก็ตามที่ผู้ใช้คลิกที่ "หัวข้อ Angular JS" หรือ "หัวข้อ Node JS"
ขั้นตอน 4) ในแท็กสคริปต์ของคุณสำหรับ AngularJS ให้เพิ่ม “โมดูล ngRoute” และบริการ “$routeProvider”
Code คำอธิบาย:
- ติดตั้งโมดูล “ngRoute” เมื่อติดตั้งโมดูลนี้แล้ว Angular จะจัดการการกำหนดเส้นทางโดยอัตโนมัติและเข้าใจคำสั่งการกำหนดเส้นทางทั้งหมด
- $routeProvider เป็นบริการที่คอยรับฟังเส้นทางที่ถูกเรียกใช้ในเบื้องหลัง เมื่อผู้ใช้คลิกลิงก์ บริการนี้จะตรวจจับได้และตัดสินใจว่าจะใช้เส้นทางใด
- สร้างเส้นทางเดียวสำหรับลิงก์ Angular: เมื่อคลิกแล้ว ให้แทรก Angular.html และใช้ 'AngularController' สำหรับตรรกะทางธุรกิจ
- สร้างเส้นทางหนึ่งเส้นสำหรับลิงก์ Node ซึ่งจะแทรกไฟล์ Node.html และใช้งาน 'NodeController' ในลักษณะเดียวกัน
ขั้นตอน 5) ถัดไปคือการเพิ่มตัวควบคุมเพื่อประมวลผลตรรกะทางธุรกิจสำหรับทั้ง AngularController และ NodeController
ในแต่ละคอนโทรลเลอร์ เราจะสร้างอาร์เรย์ของคู่คีย์-ค่าเพื่อจัดเก็บชื่อหัวข้อและคำอธิบายสำหรับแต่ละหลักสูตร ตัวแปรอาร์เรย์ 'tutorial' จะถูกเพิ่มเข้าไปในออบเจ็กต์ขอบเขตสำหรับแต่ละคอนโทรลเลอร์
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> </head> <body ng-app="sampleApp"> <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script> <script src="https://code.angularjs.org/1.8.3/angular-route.js"></script> <h1> Guru99 Global Event</h1> <div class="container"> <ul> <li><a href="#!/Angular">Angular JS Topics</a></li> <li><a href="#!/Node">Node JS Topics</a></li> </ul> <div ng-view></div> </div> <script> var sampleApp = angular.module('sampleApp', ['ngRoute']); sampleApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/Angular', { templateUrl: 'Angular.html', controller: 'AngularController' }). when('/Node', { templateUrl: 'Node.html', controller: 'NodeController' }); }]); sampleApp.controller('AngularController', function($scope) { $scope.tutorial = [ {Name: "Controllers", Description: "Controllers in action"}, {Name: "Models", Description: "Models and binding data"}, {Name: "Directives", Description: "Flexibility of Directives"} ]; }); // NodeController follows the same shape with Node.js topics sampleApp.controller('NodeController', function($scope) { $scope.tutorial = [{Name: "Promises", Description: "Power of Promises"}]; }); </script> </body> </html>
⚠️ มีการแก้ไขแล้ว การขอ <title> ป้ายติดอยู่ข้างใน <body>, chrset="UTF 8" สะกดผิด ลิงก์ที่สองชี้ไปที่ #Node.html แทนที่จะใช้เส้นทางที่ลงทะเบียนไว้ /Nodeและเส้นทางเทมเพลตจะมีเครื่องหมายทับนำหน้าซึ่งจะแยกออกมาจากรากของโดเมน
ขั้นตอน 6) สร้างเพจชื่อ Angular.html และ Node.html สำหรับแต่ละหน้า เรากำลังดำเนินการตามขั้นตอนด้านล่าง
ขั้นตอนเหล่านี้จะทำให้แน่ใจว่าคู่คีย์-ค่าทั้งหมดของอาร์เรย์จะแสดงในแต่ละหน้า
- การใช้ คำสั่ง ng-ซ้ำ เพื่อวนไปทีละคู่คีย์-ค่าที่กำหนดไว้ในตัวแปรของบทเรียน
- การแสดงชื่อและคำอธิบายของคู่คีย์-ค่าแต่ละคู่
- Angular.html
<h2>Angular</h2> <ul ng-repeat="ptutor in tutorial"> <li>Course : {{ptutor.Name}} - {{ptutor.Description}}</li> </ul>
- โหนด.html — เหมือนกับรายการด้านบนทุกประการ เพียงแต่เปลี่ยนหัวข้อเป็น “โหนด” ทั้งสองแม่แบบอ่านได้เหมือนกัน
tutorialตัวแปร ซึ่งตัวควบคุมแต่ละตัวจะส่งมาจากขอบเขตของตนเอง
⚠️ การแก้ไข: หัวข้อในไฟล์ Angular.html เดิมเขียนว่า “Anguler” การสะกดคำถูกต้องแล้วด้านบน
หากโค้ดทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏขึ้นเมื่อคุณรันโค้ดในเบราว์เซอร์
Output:
หากคุณคลิกที่ลิงก์ AngularJS Topics จะแสดงผลลัพธ์ดังต่อไปนี้
ผลลัพธ์แสดงให้เห็นชัดเจนว่า
- เมื่อคลิกลิงก์ “หัวข้อ JS เชิงมุม” ผู้ให้บริการเส้นทางที่เราประกาศในโค้ดของเราตัดสินใจว่าควรแทรกโค้ด Angular.html
- โค้ดนี้จะถูกแทรกลงในแท็ก “div” ซึ่งมีคำสั่ง ng-view นอกจากนี้ เนื้อหาสำหรับคำอธิบายหลักสูตรยังมาจาก “ตัวแปรการสอน” ซึ่งเป็นส่วนหนึ่งของวัตถุขอบเขตที่กำหนดใน AngularController
- เมื่อมีผู้คลิกที่ Node.js หัวข้อ ผลลัพธ์เดียวกันจะเกิดขึ้น และมุมมองของหัวข้อ Node.js จะปรากฏขึ้น
- นอกจากนี้ โปรดสังเกตว่าหน้าเว็บ URL ยังคงเหมือนเดิม มีเพียงเส้นทางหลังแท็ก # เท่านั้นที่เปลี่ยนแปลง และนี่คือแนวคิดของแอปพลิเคชันหน้าเดียว แท็ก #hash ใน URL เป็นตัวคั่นระหว่างเส้นทาง (ซึ่งในกรณีของเราคือ 'Angular') และหน้า HTML หลัก (Sample.html)
ตัวอย่างนี้ใช้งานได้เฉพาะเมื่อผู้ใช้คลิกลิงก์ที่ตรงกับเส้นทางที่ลงทะเบียนไว้เท่านั้น ส่วนถัดไปจะอธิบายสิ่งที่ควรเกิดขึ้นเมื่อไม่มีลิงก์ใดตรงกัน
การสร้างเส้นทางเริ่มต้นใน AngularJS
การกำหนดเส้นทางใน AngularJS ยังอำนวยความสะดวกในการมีเส้นทางเริ่มต้น นี่คือเส้นทางที่ถูกเลือกหากไม่มีการจับคู่กับเส้นทางที่มีอยู่
เส้นทางเริ่มต้นจะถูกสร้างขึ้นโดยการเพิ่มเงื่อนไขต่อไปนี้เมื่อกำหนดบริการ $routeProvider
ไวยากรณ์ด้านล่างนี้หมายถึงการเปลี่ยนเส้นทางไปยังหน้าอื่นหากเส้นทางที่มีอยู่ไม่ตรงกัน
otherwise({
redirectTo: 'page'
});
ลองใช้ตัวอย่างเดียวกันข้างต้นและเพิ่มเส้นทางเริ่มต้นให้กับบริการ $routeProvider ของเรา
sampleApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/Angular', { templateUrl: 'Angular.html', controller: 'AngularController' }). when('/Node', { templateUrl: 'Node.html', controller: 'NodeController' }). otherwise({ redirectTo: '/Angular' }); }]);
Code คำอธิบาย:
- ต่อไปนี้เราใช้โค้ดเดียวกันกับด้านบน โดยมีข้อแตกต่างเพียงอย่างเดียวคือ เราใช้คำสั่ง otherwise และตัวเลือก “redirectTo” เพื่อระบุว่าควรโหลดวิวใดหากไม่มีการระบุเส้นทาง ในกรณีของเรา เราต้องการให้แสดงวิว '/Angular'
หากโค้ดทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏขึ้นเมื่อคุณรันโค้ดในเบราว์เซอร์
Output:
จากผลลัพธ์ที่ได้
- คุณจะเห็นได้อย่างชัดเจนว่ามุมมองเริ่มต้นที่แสดงคือมุมมองของ AngularJS
- เนื่องจากเมื่อโหลดหน้าเพจ มันจะไปที่ตัวเลือก 'otherwise' ในฟังก์ชัน $routeProvider และโหลดมุมมอง '/Angular'
เส้นทางเริ่มต้นจะเป็นตัวกำหนดว่ามุมมองใดจะถูกโหลด ส่วนถัดไปจะกล่าวถึงวิธีการที่เส้นทางเดียวสามารถให้บริการข้อมูลได้หลายรายการโดยการส่งค่าเข้าไปใน URL.
วิธีการเข้าถึงพารามิเตอร์จากเส้นทาง AngularJS
Angular ยังมีฟังก์ชันการส่งพารามิเตอร์ระหว่างการกำหนดเส้นทางด้วย โดยพารามิเตอร์จะถูกเพิ่มเข้าไปที่ส่วนท้ายของเส้นทาง URL, ตัวอย่างเช่น, http://guru99/index.html#/Angular/1- ในตัวอย่างการกำหนดเส้นทางเชิงมุมนี้
- http://guru99/index.html เป็นแอปพลิเคชันหลักของเรา URL
- สัญลักษณ์ # เป็นตัวคั่นระหว่างแอปพลิเคชันหลัก URL และเส้นทาง
- เชิงมุมคือเส้นทางของเรา
- และสุดท้าย '1' คือพารามิเตอร์ที่ถูกเพิ่มเข้าไปในเส้นทางของเรา
ไวยากรณ์ทั่วไปคือ HTMLPage#/เส้นทาง/พารามิเตอร์ดังนั้นหัวข้อก่อนหน้านี้จึงกลายเป็น Sample.html#/Angular/1, #/Angular/2 และ #/Angular/3 โดยที่ตัวเลขคือ topicid
เรามาดูรายละเอียดกันว่าเราจะสร้างเส้นทาง (route) ใน Angular โดยมีพารามิเตอร์ได้อย่างไร
ขั้นตอนที่ 1) เพิ่มโค้ดต่อไปนี้ลงในมุมมองของคุณ
- เพิ่มตารางเพื่อแสดงหัวข้อทั้งหมดของหลักสูตร Angular JS ให้ผู้ใช้เห็น
- เพิ่มแถวในตารางเพื่อแสดงหัวข้อ “ตัวควบคุม” สำหรับแถวนี้ ให้ตั้งค่า href เป็น “#!/Angular/1” เพื่อให้เมื่อคลิกที่หัวข้อ จะส่งพารามิเตอร์ 1 เข้าไป URL พร้อมกับเส้นทางนั้น ๆ
- เพิ่มแถวสำหรับหัวข้อ “Models” โดยตั้งค่า href เป็น “#!/Angular/2” เพื่อให้พารามิเตอร์ที่ 2 เคลื่อนที่ไปตามแถวนั้น URL.
- เพิ่มแถวสำหรับหัวข้อ “Directives” โดยตั้งค่า href เป็น “#!/Angular/3” เพื่อให้พารามิเตอร์ที่ 3 เดินทางไปในแถวนั้น URL.
ขั้นตอนที่ 2) เพิ่ม topic id ในฟังก์ชันบริการ routeProvider
ในฟังก์ชันบริการ routeProvider ให้เพิ่ม :topicId ตัวยึดตำแหน่งเพื่อระบุว่าพารามิเตอร์ใด ๆ ที่ส่งผ่านเข้ามา URL หลังจากนั้นควรกำหนดเส้นทางให้กับตัวแปร topicId
ขั้นตอนที่ 3) เพิ่มรหัสที่จำเป็นลงในคอนโทรลเลอร์
- โปรดตรวจสอบให้แน่ใจว่าได้เพิ่ม “$routeParams” เป็นพารามิเตอร์ก่อนเมื่อกำหนดฟังก์ชันคอนโทรลเลอร์ พารามิเตอร์นี้จะสามารถเข้าถึงพารามิเตอร์เส้นทางทั้งหมดที่ส่งเข้ามาได้ URL.
- “$routeParams” เก็บค่า topicId ที่ส่งมาในเส้นทาง กำลังแนบ
$routeParams.topicIdตามขอบเขตที่กำหนด$scope.tutorialidทำให้สามารถดูได้โดยใช้ tutorialid
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> </head> <body ng-app="sampleApp"> <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script> <script src="https://code.angularjs.org/1.8.3/angular-route.js"></script> <h1> Guru99 Global Event</h1> <table class="table table-striped"> <tbody> <tr><td>1</td><td>Controllers</td> <td><a href="#!/Angular/1">Topic details</a></td></tr> <!-- rows 2 and 3 repeat with /Angular/2 and /Angular/3 --> </tbody> </table> <div ng-view></div> <script> var sampleApp = angular.module('sampleApp', ['ngRoute']); sampleApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/Angular/:topicId', { templateUrl: 'Angular.html', controller: 'AngularController' }); }]); sampleApp.controller('AngularController', ['$scope', '$routeParams', function($scope, $routeParams) { $scope.tutorialid = $routeParams.topicId; }]); </script> </body> </html>
⚠️ มีการแก้ไขแล้ว ต้นฉบับใช้ตัวอักษร l แทนที่จะเป็นตัวเลข 1 in href="#Angular/l"ละเว้น ng-view คอนเทนเนอร์ ดังนั้นเทมเพลตจึงไม่มีที่แสดงผล และโหลด angular-route.js ก่อน angular.min.jsซึ่งจะทำให้เกิดข้อผิดพลาดของโมดูล
ขั้นตอนที่ 4) เพิ่มนิพจน์เพื่อแสดงค่าตัวแปร
เพิ่มนิพจน์เพื่อแสดงตัวแปร Tutorialid ในหน้า Angular.html
<h2>Angular</h2> <br><br>{{tutorialid}}
หากโค้ดทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏขึ้นเมื่อคุณรันโค้ดในเบราว์เซอร์
Output:
ในหน้าจอเอาต์พุต
- หากคุณคลิกที่ลิงก์รายละเอียดหัวข้อสำหรับหัวข้อแรก เลข 1 จะถูกเพิ่มต่อท้าย URL.
- ตัวเลขนั้นจะถูกนำมาใช้เป็นอาร์กิวเมนต์ "routeParams" และสามารถเข้าถึงได้ในคอนโทรลเลอร์
การอ่านค่าพารามิเตอร์นั้นทำได้ง่าย แต่การดึงข้อมูลที่พารามิเตอร์ระบุมาก่อนที่หน้าจอแสดงผลจะปรากฏขึ้นนั้น เป็นหน้าที่ของพร็อพเพอร์ตี้ที่จะกล่าวถึงต่อไป
วิธีการโหลดข้อมูลล่วงหน้าด้วยคุณสมบัติ resolve
ตัวควบคุมในส่วนก่อนหน้านี้อ่านรหัสหัวข้อและแสดงผลทันที แต่แอปพลิเคชันจริงจะต้องดึงข้อมูลจากเซิร์ฟเวอร์ก่อน และหากการแสดงผลเสร็จสิ้นก่อนที่คำขอจะส่งคืนค่า ผู้ใช้จะเห็นเทมเพลตว่างเปล่าซึ่งจะค่อยๆ เติมข้อมูลในภายหลัง resolve คุณสมบัตินี้ช่วยขจัดช่วงเวลาแสดงเนื้อหาว่างเปล่านั้นออกไป
กุญแจแต่ละดอกภายใน resolve `object` คือส่วนประกอบที่ AngularJS เตรียมไว้ก่อนที่เส้นทางจะทำงาน หากค่าเป็น Promise เราเตอร์จะรอจนกว่า Promise นั้นจะเสร็จสมบูรณ์ เมื่อ Promise ทุกตัวได้รับการแก้ไขแล้ว AngularJS จึงจะสร้างอินสแตนซ์ของคอนโทรลเลอร์และแสดงผลเทมเพลต และค่าที่ได้รับการแก้ไขแล้วจะถูกส่งเข้าไปในคอนโทรลเลอร์โดยใช้ชื่อ เช่นเดียวกับบริการอื่นๆ
sampleApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/Angular/:topicId', { templateUrl: 'Angular.html', controller: 'AngularController', resolve: { // The router waits for this promise before rendering topic: ['$http', '$route', function($http, $route) { var id = $route.current.params.topicId; return $http.get('/api/topics/' + id).then(function(response) { return response.data; }); }] } }); }]); // 'topic' is injected already resolved, so no loading state is needed sampleApp.controller('AngularController', ['$scope', 'topic', function($scope, topic) { $scope.topic = topic; }]);
มีพฤติกรรมสองอย่างที่สำคัญในที่นี้ การปฏิเสธคำสัญญาจะยกเลิกการเปลี่ยนแปลงเส้นทางและทำให้เบราว์เซอร์ยังคงอยู่ที่มุมมองปัจจุบัน ดังนั้นคำขอที่ล้มเหลวจะไม่ทำให้หน้าเว็บเสียหาย อย่างไรก็ตาม เนื่องจากเราเตอร์จะบล็อกในขณะที่คำสัญญาอยู่ในสถานะรอการดำเนินการ ปลายทางที่ทำงานช้าจะทำให้แอปพลิเคชันดูเหมือนหยุดทำงาน (Pair) resolve โดยมีตัวชี้วัดความคืบหน้าที่ขับเคลื่อนโดย $routeChangeStart และ $routeChangeSuccess เหตุการณ์ที่เกิดขึ้น
⚠️ คำเตือน: ห้ามวางการตรวจสอบความถูกต้องไว้เฉพาะภายในเท่านั้น resolveการปฏิเสธเส้นทางจะซ่อนมุมมอง แต่จะไม่ปกป้องข้อมูลที่อยู่เบื้องหลัง และปลายทาง API ยังคงต้องบังคับใช้การเข้าถึงบนเซิร์ฟเวอร์อยู่ดี
นอกเหนือจากการโหลดข้อมูลล่วงหน้าแล้ว เส้นทางยังสามารถบรรจุค่าการกำหนดค่าแบบคงที่ได้อีกด้วย บริการที่อธิบายต่อไปนี้คือวิธีการที่คอนโทรลเลอร์อ่านค่าเหล่านั้น
วิธีใช้บริการเส้นทาง $route เชิงมุม
บริการ `$route` ช่วยให้คุณเข้าถึงคุณสมบัติของเส้นทางได้ บริการ `$route` สามารถใช้งานได้ในฐานะพารามิเตอร์เมื่อมีการกำหนดฟังก์ชันในคอนโทรลเลอร์ รูปแบบทั่วไปของการใช้งานพารามิเตอร์ `$route` จากคอนโทรลเลอร์แสดงไว้ด้านล่าง
myApp.controller('MyController', function($scope, $route) { ... });
- myApp คือโมดูล AngularJS ที่กำหนดไว้สำหรับแอปพลิเคชันของคุณ
- MyController คือชื่อของคอนโทรลเลอร์ที่กำหนดไว้สำหรับแอปพลิเคชันของคุณ
- เช่นเดียวกับที่ $scope ส่งต่อข้อมูลจากคอนโทรลเลอร์ไปยังวิว $route ก็แสดงคุณสมบัติของเส้นทางปัจจุบันเช่นกัน
มาดูกันว่าเราสามารถใช้บริการ $route ได้อย่างไร
ในตัวอย่างนี้
- เราจะสร้างตัวแปรที่กำหนดเองอย่างง่ายที่เรียกว่า "mytext" ซึ่งจะมีสตริง "นี่คือเชิงมุม"
- เราจะเพิ่มตัวแปรนี้เข้าไปในเส้นทางของเรา Later เราจะเข้าถึงสตริงนี้จากคอนโทรลเลอร์ของเราโดยใช้บริการ $route จากนั้นใช้ object scope เพื่อแสดงผลในวิวของเรา
เรามาดูขั้นตอนที่เราต้องทำเพื่อให้บรรลุเป้าหมายนี้กัน
ขั้นตอน 1) เพิ่มคู่คีย์-ค่าที่กำหนดเองให้กับเส้นทาง ที่นี่ เรากำลังเพิ่มคีย์ที่เรียกว่า 'mytext' และกำหนดค่าเป็น "นี่คือเชิงมุม"
ขั้นตอน 2) เพิ่มโค้ดที่เกี่ยวข้องลงในคอนโทรลเลอร์
- เพิ่มพารามิเตอร์ `$route` ลงในฟังก์ชันคอนโทรลเลอร์ พารามิเตอร์ `$route` เป็นพารามิเตอร์สำคัญที่กำหนดไว้ใน Angular ซึ่งช่วยให้สามารถเข้าถึงคุณสมบัติของเส้นทางได้
- ตัวแปร “mytext” ที่กำหนดไว้ในเส้นทางสามารถเข้าถึงได้ผ่านการอ้างอิง $route.current จากนั้นจะกำหนดให้กับตัวแปร 'ข้อความ' ของวัตถุขอบเขต ตัวแปรข้อความสามารถเข้าถึงได้จากมุมมองตามลำดับ
// Only the config and controller change; the page markup is unchanged sampleApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/Angular/:topicId', { mytext: "This is angular", // custom key attached to the route templateUrl: 'Angular.html', controller: 'AngularController' }); }]); sampleApp.controller('AngularController', ['$scope', '$routeParams', '$route', function($scope, $routeParams, $route) { $scope.tutorialid = $routeParams.topicId; $scope.text = $route.current.mytext; }]);
ขั้นตอน 3) เพิ่มการอ้างอิงถึงตัวแปรข้อความจากวัตถุขอบเขตเป็นนิพจน์ สิ่งนี้จะถูกเพิ่มลงในหน้า Angular.html ของเราดังที่แสดงด้านล่าง
ซึ่งจะทำให้ข้อความ "นี่คือเชิงมุม" ถูกแทรกเข้าไปในมุมมอง นิพจน์ {{tutorialid}} เหมือนกับที่เห็นในหัวข้อที่แล้ว และจะแสดงตัวเลข '1'
<h2>Angular</h2> <br><br>{{text}} <br><br>{{tutorialid}}
หากโค้ดทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏขึ้นเมื่อคุณรันโค้ดในเบราว์เซอร์
Output:
จากผลลัพธ์ที่ได้
- เราจะเห็นว่าข้อความ "This is angular" จะปรากฏขึ้นเมื่อเราคลิกลิงก์ใดๆ ในตาราง นอกจากนี้ ID หัวข้อยังจะปรากฏขึ้นพร้อมกันกับข้อความด้วย
ทุกๆ URL ส่วนที่แสดงอยู่นี้ยังคงมีสัญลักษณ์ # อยู่ ขั้นตอนการตั้งค่าขั้นสุดท้ายจะลบสัญลักษณ์นี้ออก
การเปิดใช้งานการกำหนดเส้นทาง HTML5
การกำหนดเส้นทาง HTML5 ถูกนำมาใช้เพื่อสร้างโครงสร้างที่สะอาดตา URLหมายความว่า การลบแฮชแท็กออกจาก URLดังนั้นการกำหนดเส้นทาง URLเมื่อใช้การกำหนดเส้นทาง HTML5 จะปรากฏดังที่แสดงด้านล่าง
ตัวอย่าง.html/Angular/1
ตัวอย่าง.html/Angular/2
ตัวอย่าง.html/Angular/3
แนวคิดนี้โดยทั่วไปรู้จักกันในชื่อการนำเสนอที่สวยงาม URL ให้กับผู้ใช้
มี 2 ขั้นตอนหลักที่ต้องดำเนินการสำหรับการกำหนดเส้นทาง HTML5
- การกำหนดค่า $locationProvider
- การตั้งค่าฐานของเราสำหรับลิงค์ที่เกี่ยวข้อง
เรามาดูรายละเอียดวิธีการดำเนินการตามขั้นตอนต่างๆ ในตัวอย่างของเรากัน
ขั้นตอน 1) เพิ่มโค้ดที่เกี่ยวข้องลงในโมดูล Angular
- เพิ่ม
<base>เพิ่มแท็ก <head> ลงในส่วนหัวของเอกสาร สิ่งนี้จำเป็นสำหรับการกำหนดเส้นทางใน HTML5 เพื่อให้แอปพลิเคชันทราบตำแหน่งฐานของแอปพลิเคชัน - เพิ่มบริการ `$locationProvider` บริการนี้ช่วยให้คุณกำหนด `html5Mode` ได้
- ตั้งค่า html5Mode ของบริการ $locationProvider เป็นจริง
ขั้นตอน 2) ลบแท็ก # ทั้งหมดออกจากลิงก์ ('Angular/1', 'Angular/2', 'Angular/3') เพื่อให้อ่านง่ายขึ้น URLs.
<!-- In the head: required by html5Mode so relative templates resolve --> <base href="/"> <!-- In the body: the # is dropped from every link --> <a href="Angular/1">Topic details</a> <script> sampleApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) { $locationProvider.html5Mode(true); $routeProvider. when('/Angular/:topicId', { templateUrl: 'Angular.html', controller: 'AngularController' }); }]); </script>
⚠️ การแก้ไข: เดิมทีประกาศไว้ว่า baseUrl ชี้ไปยังพาธ IDE ในเครื่องอย่างคงที่ ซึ่งไม่มีผลต่อ html5Mode AngularJS อ่านตำแหน่งฐานจาก <base href> แท็ก ต้นฉบับยังฉีดเข้าไปด้วย $locationProvider โดยไม่เคยโทรเลย html5Mode(true)ดังนั้นแฮชจึงไม่เคยถูกลบออก
หากโค้ดทำงานสำเร็จ ผลลัพธ์ต่อไปนี้จะปรากฏขึ้นเมื่อคุณรันโค้ดในเบราว์เซอร์
Output:
จากผลลัพธ์ที่ได้
- คุณจะเห็นว่าไม่มีแท็ก # เมื่อเข้าถึงแอปพลิเคชัน
โค้ดด้านบนทั้งหมดใช้ ngRoute ซึ่งเป็นเราเตอร์ที่ทีม AngularJS จัดส่งมาให้ อย่างไรก็ตาม มันไม่ใช่ตัวเลือกเดียว และการเปรียบเทียบด้านล่างจะอธิบายว่าเมื่อใดที่ตัวเลือกอื่นเหมาะสมกว่า
ngRoute กับ ui-router: ควรเลือกใช้เราเตอร์ตัวไหนดี
ngRoute ถูกดูแลโดยทีม AngularJS และตรงกับ... URL โดยตรงไปยังเทมเพลตและคอนโทรลเลอร์เดียว ui-router เป็นโปรเจกต์จากชุมชนที่สร้างขึ้นเพื่อขจัดข้อจำกัดหลักของ ngRoute: คือการจับคู่ตามแอปพลิเคชัน รัฐ แทนที่จะอยู่บน URL โดยลำพัง ซึ่งทำให้หน้าจอเดียวสามารถบรรจุพื้นที่ที่เชื่อมต่อกันอย่างอิสระได้หลายส่วน
| แง่มุม | ngRoute | เราเตอร์ UI |
|---|---|---|
| บริการการกำหนดค่า | $routeProvider | $stateProvider |
| การแข่งขันบน | URL เพียง | รัฐที่มีชื่อ, URL ไม่จำเป็น |
| มุมมองแบบซ้อนกัน | ไม่ได้รับการสนับสนุน | ที่สนับสนุน |
| หลายมุมมองต่อหน้าจอ | หนึ่งมุมมอง | เต้ารับ UI-View ที่มีชื่อจำนวนมาก |
| การแก้ไขแบบซ้อนกัน | ไม่ได้รับการสนับสนุน | สถานะของลูกจะสืบทอดการแก้ไขจากสถานะแม่ |
| เหมาะที่สุดสำหรับ | ใช้งานแบบแบนและขนาดเล็ก | แดชบอร์ดและเลย์เอาต์แบบเลเยอร์ |
เลือก ngRoute เมื่อแต่ละครั้ง URL แมปไปยังมุมมองเต็มหน้าจอเดียว เนื่องจากไม่ต้องการการพึ่งพาเพิ่มเติม และ API ทั้งหมดพอดีกับหน้าเดียว เลือกใช้ ui-router เมื่อหน้าจอมีบานหน้าต่างที่นำทางอย่างอิสระ หรือเมื่อมุมมองย่อยต้องใช้ข้อมูลที่โหลดโดยมุมมองหลักซ้ำ การย้ายไปใช้ในภายหลังเป็นไปได้ แต่ไม่ใช่เรื่องง่าย เนื่องจากชื่อสถานะจะเข้ามาแทนที่ URL ลวดลายต่างๆ ปรากฏอยู่ทั่วทั้งแม่แบบ
ข้อผิดพลาดทั่วไปในการกำหนดเส้นทาง (Routing) ใน AngularJS และวิธีแก้ไข
ความล้มเหลวในการกำหนดเส้นทางส่วนใหญ่มักทำให้หน้าต่าง ng-view แสดงผลว่างเปล่าแทนที่จะแสดงข้อผิดพลาดในคอนโซล ซึ่งทำให้การวินิจฉัยทำได้ยากกว่าที่ควรจะเป็น อาการแต่ละอย่างด้านล่างจะระบุสาเหตุและวิธีแก้ไข
- ผู้ให้บริการที่ไม่รู้จัก: $routeProvider: ไฟล์ angular-route.js ไม่เคยถูกโหลด หรือถูกโหลดก่อนไฟล์ angular.min.js กรุณาอ้างอิงไลบรารีหลักก่อน
- หน้าจอยังคงว่างเปล่าโดยไม่มีข้อผิดพลาดใดๆ: ไม่มีองค์ประกอบใดที่ใช้คำสั่ง ng-view ดังนั้นเทมเพลตจึงไม่มีที่สำหรับแสดงผล
- ไม่มีข้อมูลโหลดในการเข้าชมครั้งแรก: ไม่มีเส้นทางใดตรงกับเส้นทางว่างเปล่า เพิ่มบล็อก otherwise พร้อมค่า redirectTo
- $routeParams ว่างเปล่า: รูปแบบนี้ขาดตัวยึดตำแหน่งเครื่องหมายโคลอน ที่ถูกต้องควรเป็น '/Angular/:topicId'
- เทมเพลตแสดงข้อผิดพลาด 404 หลังจาก html5Mode: กำหนดค่าเซิร์ฟเวอร์ให้เขียนเส้นทางที่ไม่ตรงกันใหม่ไปยังหน้าหลัก และตรวจสอบว่าแท็ก href ของหน้าหลักมีอยู่หรือไม่
- ตัวควบคุมจะไม่ทำงานซ้ำอีก: มีเพียงพารามิเตอร์เท่านั้นที่เปลี่ยนแปลง ดังนั้น AngularJS จึงนำอินสแตนซ์ของคอนโทรลเลอร์มาใช้ซ้ำแทนที่จะสร้างใหม่ทั้งหมด ควรฟังเหตุการณ์ `$routeUpdate` แทนที่จะรอให้ฟังก์ชันของคอนโทรลเลอร์ทำงานอีกครั้ง
























