ถึงเวลาที่จะให้คุณสมบัติบางอย่างแบบไดนามิกเหล่านี้ - ใช้ AngularJS! เราได้เพิ่มการทดสอบสำหรับคอนโทรลเลอร์ที่จะเพิ่มในภายหลัง
มีสถาปัตยกรรมรหัสหลายประเภทสำหรับแอปพลิเคชัน สำหรับแอปพลิเคชัน AngularJS เราขอแนะนำให้ใช้โหมด Model-View-Controller (MVC) เพื่อแยกรหัสและแยกข้อกังวลแยกต่างหาก ด้วยสิ่งนี้ในใจเราใช้ AngularJS เพื่อเพิ่มบางรุ่นมุมมองและตัวควบคุมในแอปพลิเคชันของเรา
โปรดรีเซ็ตไดเรกทอรีการทำงาน:
git checkout -f step -2
แอพของเราตอนนี้มีรายการโทรศัพท์สามเครื่อง
ความแตกต่างที่สำคัญที่สุดระหว่างขั้นตอนที่ 1 และขั้นตอนที่ 2 แสดงอยู่ด้านล่าง คุณสามารถไปที่ GitHub เพื่อดูความแตกต่างที่สมบูรณ์
มุมมองและแม่แบบ
ใน AngularJS มุมมองคือการทำแผนที่หลังจากที่โมเดลจะแสดงผลผ่านเทมเพลต HTML ** ซึ่งหมายความว่าไม่ว่าแบบจำลองจะเปลี่ยนไปเมื่อใด AngularJS จะอัปเดตจุดเชื่อมต่อแบบเรียลไทม์และอัปเดตมุมมอง
ตัวอย่างเช่นองค์ประกอบมุมมองถูกสร้างขึ้นโดย AngularJS โดยใช้เทมเพลตต่อไปนี้:
<html ng-app> <head> ... <script src = "lib/angular/angular.js"> </script> <script src = "js/controllers.js"> </script> </head> <body ng-controller = "phonelistctrl"> <ul> <p> {{phone.snippet}} </p> </li></ul> </body> </html>เราเพิ่งแทนที่รายการโทรศัพท์มือถือที่เข้ารหัสแบบคงที่เพราะเราสามารถบรรลุเอฟเฟกต์เดียวกันโดยใช้คำสั่ง ngrepeat และนิพจน์ AngularJs สองอันที่ห่อหุ้มด้วยการจัดฟันแบบหยิก - {{phone.name}} และ {{phone.snippet}}
คำสั่ง ng-repeat = "โทรศัพท์ในโทรศัพท์" ภายในแท็ก <li> เป็นตัววนซ้ำ AngularJS ตัววนซ้ำนี้บอกให้ AngularJS ใช้แท็ก <li> แรกเป็นเทมเพลตเพื่อสร้างองค์ประกอบ <li> สำหรับโทรศัพท์แต่ละเครื่องในรายการ
ดังที่เราได้เรียนรู้ในขั้นตอนที่ 0 การจัดฟันดัดผมล้อมรอบโทรศัพท์ชื่อและโทรศัพท์ snippet ระบุการเชื่อมโยงข้อมูล ซึ่งแตกต่างจากการคำนวณอย่างต่อเนื่องนิพจน์ที่นี่คือการอ้างอิงแบบจำลองข้อมูลที่เราใช้และเราได้ตั้งค่าเหล่านี้ในคอนโทรลเลอร์ PhonelistCtrl
แบบจำลองและคอนโทรลเลอร์
รูปแบบข้อมูลจะเริ่มต้นในคอนโทรลเลอร์ PhonelistCtrl (นี่เป็นเพียงฟังก์ชั่นที่มีอาร์เรย์และวัตถุที่เก็บไว้ในอาร์เรย์เป็นรายการข้อมูลมือถือ):
แอพ/js/controller.js:
ฟังก์ชั่น phonelistctrl ($ scope) {$ scope.phones = [{"name": "nexus s", "snippet": "เร็วเพิ่งเร็วขึ้นด้วย Nexus S. "}, {"ชื่อ": "Motorola Xoom ™กับ Wi-Fi", "Snippet" "ตัวอย่าง": "แท็บเล็ตรุ่นต่อไปถัดไป"}];}แม้ว่าคอนโทรลเลอร์ดูเหมือนจะไม่ได้มีบทบาทสำคัญมาก แต่ก็มีบทบาทสำคัญที่นี่ ด้วยบริบทของโมเดลข้อมูลของเราคอนโทรลเลอร์ช่วยให้เราสามารถสร้างการเชื่อมโยงข้อมูลระหว่างโมเดลและมุมมอง นี่คือวิธีที่เราเชื่อมโยงเลเยอร์การนำเสนอข้อมูลและส่วนประกอบตรรกะ:
PhonelistCtrl - ชื่อของวิธีการควบคุม (ในตัวควบคุมไฟล์ JS) ตรงกับค่าของคำสั่ง ngController ในแท็ก <body>
ขณะนี้ข้อมูลของโทรศัพท์เชื่อมโยงกับขอบเขต ($ $) ที่ฉีดลงในฟังก์ชั่นคอนโทรลเลอร์ของเรา เมื่อแอปพลิเคชันเริ่มต้นขอบเขตรูทจะถูกสร้างขึ้นและขอบเขตคอนโทรลเลอร์เป็นตัวตายตัวแทนทั่วไปไปยังขอบเขตรูท ขอบเขตของคอนโทรลเลอร์นี้ใช้ได้สำหรับการผูกข้อมูลภายในแท็ก <body ng-controller = "phonelistctrl"> แท็ก
ทฤษฎีขอบเขตของ AngularJS มีความสำคัญมาก: ขอบเขตสามารถถือได้ว่าเป็น bonder สำหรับเทมเพลตโมเดลและคอนโทรลเลอร์ที่จะทำงานร่วมกัน AngularJS ใช้ขอบเขตเช่นเดียวกับข้อมูลโมเดลข้อมูลและตัวควบคุมในเทมเพลต สิ่งเหล่านี้สามารถช่วยแยกโมเดลและมุมมองออกได้ แต่พวกเขาจะซิงโครไนซ์แน่นอน! การเปลี่ยนแปลงใด ๆ ของโมเดลจะสะท้อนให้เห็นในมุมมองทันที การเปลี่ยนแปลงใด ๆ ในมุมมองจะสะท้อนให้เห็นในโมเดลทันที
สำหรับความเข้าใจในเชิงลึกเกี่ยวกับขอบเขต AngularJS โปรดดูเอกสารขอบเขต AngularJS
ทดสอบ
วิธีการ "AngularJS" ทำให้ง่ายต่อการทดสอบรหัสในระหว่างการพัฒนา มาดูการทดสอบหน่วยต่อไปนี้ที่เพิ่มขึ้นใหม่สำหรับคอนโทรลเลอร์:
ทดสอบ/หน่วย/controllersspec.js:
อธิบาย ('phonecat controllers', function () {อธิบาย ('phonelistctrl', function () {มัน ('ควรสร้างโมเดล "โทรศัพท์" ด้วยโทรศัพท์ 3 เครื่อง', ฟังก์ชั่น () {var scope = {}, ctrl = new PhonelistCtrl (ขอบเขต);การทดสอบนี้ตรวจสอบว่ามีสามระเบียนในอาร์เรย์โทรศัพท์มือถือของเรา (ไม่จำเป็นต้องเข้าใจสคริปต์ทดสอบนี้ในขณะนี้) ตัวอย่างนี้แสดงให้เห็นว่ามันง่ายเพียงใดในการสร้างการทดสอบหน่วยสำหรับรหัส AngularJS เนื่องจากการทดสอบเป็นส่วนสำคัญของการพัฒนาซอฟต์แวร์เราจึงทำให้ง่ายต่อการสร้างการทดสอบใน AngularJS เพื่อกระตุ้นให้นักพัฒนาเขียนมากขึ้น
เมื่อเขียนการทดสอบนักพัฒนา AngularJS มักจะใช้ไวยากรณ์ในกรอบการพัฒนาที่ขับเคลื่อนด้วยพฤติกรรมของจัสมิน (BBD) แม้ว่า AngularJS จะไม่บังคับให้คุณใช้จัสมิน แต่การทดสอบทั้งหมดที่เรามีในการสอนจะถูกเขียนขึ้นในจัสมิน คุณสามารถได้รับความรู้ที่เกี่ยวข้องเกี่ยวกับหน้าแรกอย่างเป็นทางการของจัสมินหรือในวิกิจัสมิน
โครงการที่ใช้ AngularJS ได้รับการกำหนดค่าล่วงหน้าเพื่อใช้ JstestDriver เพื่อเรียกใช้การทดสอบหน่วย คุณสามารถเรียกใช้การทดสอบแบบนี้:
ในเทอร์มินัลแยกต่างหากให้ป้อนไดเรกทอรี Angular-Phonecat และ Run ./scripts/test-server.sh เพื่อเริ่มการทดสอบ (โปรดป้อน./scripts/test-server.bat บนบรรทัดคำสั่ง Windows เพื่อเรียกใช้สคริปต์และคำสั่งสคริปต์ทำงานในวิธีต่อไปนี้);
เปิดหน้าต่างเบราว์เซอร์ใหม่และไปที่ http: // localhost: 9876;
เลือกจับเบราว์เซอร์นี้ในโหมดที่เข้มงวด
ในเวลานี้คุณสามารถออกจากหน้าต่างของคุณคนเดียวและลืมมันไป JstestDriver จะทำการทดสอบและส่งออกผลลัพธ์ไปยังเทอร์มินัลของคุณ
Run ./scripts/test.sh เพื่อทดสอบ
คุณควรเห็นผลลัพธ์คล้ายกับสิ่งต่อไปนี้:
Chrome: Runner Reset .. Total 1 การทดสอบ (ผ่าน: 1; Fails: 0; ข้อผิดพลาด: 0) (2.00 ms) Chrome 19.0.1084.36 Mac OS: Run 1 การทดสอบ (ผ่าน: 1; Fails: 0; ข้อผิดพลาด 0) (2.00 ms)
ใช่! การทดสอบผ่านไป! หรือไม่ ... หมายเหตุ: หากมีข้อผิดพลาดเกิดขึ้นหลังจากที่คุณเรียกใช้การทดสอบให้ปิดเบราว์เซอร์และกลับไปที่เทอร์มินัลและปิดสคริปต์แล้วทำซ้ำขั้นตอนด้านบน
ฝึกฝน
เพิ่มการเชื่อมโยงข้อมูลอื่นสำหรับ index.html ตัวอย่างเช่น:
<p> จำนวนโทรศัพท์ทั้งหมด: {{phone.length}} </p>
สร้างคุณสมบัติโมเดลข้อมูลใหม่และผูกกับเทมเพลต ตัวอย่างเช่น:
$ scope.hello = "สวัสดีโลก!"
อัปเดตเบราว์เซอร์ของคุณและตรวจสอบให้แน่ใจว่า "สวัสดีโลก!" ปรากฏขึ้น
สร้างตารางง่ายๆด้วยตัววนซ้ำ:
<table> <tr> <th> หมายเลขแถว </th> </tr> <tr ng-repeat = "i ใน [0, 1, 2, 3, 4, 5, 6, 7]"> <td> {{i}} </td> </tr> </table>ตอนนี้ให้ I ของการแสดงออกของแบบจำลองข้อมูลเพิ่มขึ้น 1:
<table> <tr> <th> หมายเลขแถว </th> </tr> <tr ng-repeat = "i ใน [0, 1, 2, 3, 4, 5, 6, 7]"> <td> {{i+1}} </td>ตรวจสอบให้แน่ใจว่าได้เปลี่ยน tobe (3) เป็น tobe (4) จากนั้นเรียกใช้./scripts/test.sh สคริปต์อีกครั้ง
สรุป
ตอนนี้คุณมีแอปพลิเคชันแบบไดนามิกของแบบจำลองมุมมองการแยกคอนโทรลเลอร์และคุณกำลังทดสอบอยู่เสมอ ตอนนี้คุณสามารถไปที่ขั้นตอนที่ 3 เพื่อเพิ่มฟังก์ชั่นการค้นหาข้อความเต็มไปยังแอปพลิเคชัน
ข้างต้นคือข้อมูลการแยกเทมเพลต AngularJS เราจะยังคงเพิ่มข้อมูลที่เกี่ยวข้องในอนาคต ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!