1. การฉีดพึ่งพา
การฉีดพึ่งพา (DI) เป็นรูปแบบการออกแบบซอฟต์แวร์ที่เกี่ยวข้องกับวิธีที่รหัสได้รับทรัพยากรที่ขึ้นอยู่กับ
สำหรับการอภิปรายที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับ DI คุณสามารถเยี่ยมชมการฉีดพึ่งพา (http://en.wikipedia.org/wiki/dependency_inject) การผกผันของการควบคุม (http://martinfowler.com/articles/inject.html)
1. di สั้น ๆ (พูดเพียงแค่ di)
วัตถุหรือฟังก์ชั่นสามารถรับทรัพยากรที่ขึ้นอยู่กับสามวิธีต่อไปนี้:
1) คุณสามารถสร้างทรัพยากรที่พึ่งพาได้ผ่านตัวดำเนินการใหม่
2) คุณสามารถค้นหาทรัพยากรที่พึ่งพาได้ผ่านตัวแปรทั่วโลก
3) ทรัพยากรที่ขึ้นอยู่กับพารามิเตอร์
ทั้งสองวิธี 1 และ 2 ไม่ดีที่สุดเพราะพวกเขาใช้รหัสการพึ่งพาซึ่งทำให้ไม่สามารถปรับเปลี่ยนการพึ่งพาได้ แต่มันจะซับซ้อนมากขึ้น นี่เป็นปัญหาโดยเฉพาะอย่างยิ่งสำหรับการทดสอบและโดยปกติเมื่อทำการทดสอบอย่างอิสระมันเป็นที่ต้องการเพื่อให้การพึ่งพาจำลอง
วิธีที่สามนั้นค่อนข้างเป็นไปได้มากที่สุดเพราะจะช่วยขจัดความรับผิดชอบของการค้นหาการพึ่งพาจากส่วนประกอบ การพึ่งพาเป็นเพียงการส่งมอบส่วนประกอบ
ฟังก์ชั่น someClass (greeter) {this.greeter = greeter} someclass.prototype.dosomething = function (ชื่อ) {this.greeter.greet (ชื่อ);}ในตัวอย่างข้างต้น Someclass ไม่จำเป็นต้องใส่ใจเกี่ยวกับการค้นหาการพึ่งพาของ Greeter มันผ่าน Greeter เมื่อรันไทม์เท่านั้น
สิ่งนี้เหมาะสมกว่า แต่จะทำให้ความรับผิดชอบในการได้รับทรัพยากรการพึ่งพากับรหัสที่รับผิดชอบในการสร้าง someclass
เพื่อจัดการความรับผิดชอบในการสร้างการพึ่งพาแอปพลิเคชันเชิงมุมแต่ละตัวมีหัวฉีด (http://code.angularjs.org/1.0.2/docs/api/angular.injector) หัวฉีดเป็นตัวระบุตำแหน่งบริการที่รับผิดชอบในการค้นหาและสร้างทรัพยากรที่ต้องพึ่งพา
การร้องขอการพึ่งพา, แก้ปัญหาของรหัสยาก แต่ก็หมายความว่าหัวฉีดจำเป็นต้องทำงานผ่านแอปพลิเคชันทั้งหมด การผ่านหัวฉีดจะทำลาย Law of Demeter (http://baike.baidu.com/view/823220.htm) เพื่อแก้ไขปัญหานี้เราจะโอนความรับผิดชอบสำหรับการค้นหาการค้นหาไปยังหัวฉีด
ฉันได้พูดไปข้างต้นมาก ดูตัวอย่างที่ฉันแก้ไขด้านล่าง ฉันได้รวมสองตัวอย่างของข้อความต้นฉบับโดยใช้การฉีดทั้งภายในและภายนอกเชิงมุม:
<! doctype html> <html lang = "zh-cn" ng-app = "mainapp"> <head> <meta charset = "utf-8"> <title> หัวฉีด </title> </head> <body> src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <script type = "text/javascript"> // สร้างโมดูลอื่น ๆ ซึ่งเทียบเท่ากับโมดูลภายนอก // สอนหัวฉีดวิธีสร้าง "greeter" // โปรดทราบว่าตัวเองต้องพึ่งพา $ window othermodule.factory ("greeter", ฟังก์ชั่น ($ window) {// นี่เป็นวิธีโรงงาน, รับผิดชอบในการสร้างทักทายบริการกลับ {ทักทาย: ฟังก์ชั่น (ข้อความ) {$ window.alert (ข้อความ); // ต่อไปนี้แสดงให้เห็นว่าในโมดูลที่ไม่ใช่ปัจจุบันโทรหาวิธีการทักทายผ่านหัวฉีด: // สร้างหัวฉีดใหม่จากโมดูล // ขั้นตอนนี้มักจะทำโดยอัตโนมัติเมื่อเริ่มต้นเชิงมุม // 'ng', สิ่งที่เป็นมุมต้องได้รับการแนะนำ // คำสั่งซื้อกลับโดยเจตนาและได้รับการยืนยันชั่วคราวว่าคำสั่งของสิ่งนี้ไม่สำคัญ - var injector = angular.injector (['othermodule', 'ng']); // ขอการพึ่งพาของ Greeter var g = injector.get ("greeter"); // เรียกมันโดยตรง ~ g.greet ("สวัสดี ~ dada ตัวน้อยของฉัน ~"); // นี่คือแอพหลักปัจจุบันและคุณต้องพึ่งพา othermodule var mainapp = angular.module ("MainApp", ["OtherModule"]); // ให้ความสนใจกับพารามิเตอร์ของฟังก์ชั่นนิยามของคอนโทรลเลอร์และฉีด $ SCOPE และ GREETER โดยตรงที่นี่ // The Greeter Service คือ MainApp.Controller ("MyController", Function MyController ($ SCOPE, Greeter) {$ scope.sayhello = function () {greeter.greet ("Hello Kitty ~~");};}); // ng-controller ได้ทำสิ่งนี้อย่างเงียบ ๆ หลังฉาก //injector.instantiate(Mycontroller); </script> </body> </html>โปรดทราบว่าเนื่องจากมี NG-controller ทำให้ MyController เริ่มต้นจึงสามารถพบกับการพึ่งพาทั้งหมดของ MyController เพื่อให้ MyController ไม่จำเป็นต้องรู้การมีอยู่ของหัวฉีด นี่คือผลลัพธ์ที่ดีที่สุด รหัสแอปพลิเคชันเพียงร้องขอการพึ่งพาที่ต้องการโดยไม่ต้องจัดการหัวฉีด การตั้งค่านี้จะไม่ทำลายกฎหมายของ Demeter
2. คำอธิบายประกอบการพึ่งพา (ความคิดเห็นการพึ่งพาอธิบายวิธีการพึ่งพา)
หัวฉีดรู้ว่าต้องฉีดบริการอะไรได้บ้าง?
นักพัฒนาแอปพลิเคชันจำเป็นต้องให้ข้อมูลคำอธิบายประกอบที่ใช้โดยหัวฉีดเพื่อเป็นทางออกสำหรับการพึ่งพา ฟังก์ชั่น API ที่มีอยู่ทั้งหมดใน Angular อ้างถึงหัวฉีดและนี่เป็นกรณีของ API ที่กล่าวถึงในแต่ละเอกสาร ต่อไปนี้เป็นวิธีที่เทียบเท่ากันสามวิธีในการใส่คำอธิบายประกอบรหัสของเราด้วยข้อมูลชื่อบริการ
1. การพึ่งพาการอนุมาน
นี่เป็นวิธีที่ง่ายที่สุดในการรับทรัพยากรที่ต้องพึ่งพา แต่จำเป็นต้องสมมติว่าชื่อพารามิเตอร์ของฟังก์ชั่นสอดคล้องกับชื่อของทรัพยากรที่ขึ้นอยู่กับ
ฟังก์ชั่น myController ($ scope, greeter) {... }หัวฉีดของฟังก์ชั่นสามารถเดาชื่อของบริการที่จำเป็นต้องฉีด (functionName.toString (), regexp) โดยการตรวจสอบคำจำกัดความของฟังก์ชั่นและแยกชื่อฟังก์ชัน ในตัวอย่างข้างต้น $ SCOPE และ GEETER เป็นบริการสองบริการที่ต้องฉีดเข้าไปในฟังก์ชั่น (ชื่อก็เหมือนกัน)
แม้ว่านี่จะง่าย แต่วิธีนี้จะไม่ทำงานหลังจากการบีบอัดการทำให้งงงวย JavaScript เนื่องจากชื่อพารามิเตอร์จะเปลี่ยนไป สิ่งนี้ทำให้วิธีนี้มีประโยชน์สำหรับการ pretotyping เท่านั้น (วิธีการทดสอบการจำลองต้นแบบการใช้งานผลิตภัณฑ์, http://www.pretotyping.org/, http://tech.qq.com/a/20120217/000320.htm) และแอปพลิเคชัน Demo
2. $ Inject Annotation ($ Inject Comment)
เพื่อให้คอมเพรสเซอร์สคริปต์เปลี่ยนชื่อวิธีการของฟังก์ชั่นและยังสามารถฉีดบริการที่ถูกต้องฟังก์ชั่นจะต้องแสดงความคิดเห็นเกี่ยวกับการพึ่งพาผ่านคุณสมบัติ $ inject คุณสมบัติ $ inject เป็นอาร์เรย์ของชื่อของบริการที่ต้องฉีด
var myController = function (เปลี่ยนชื่อ $ scope, RenamedGreeter) {... } // ถ้าสิ่งที่ขึ้นอยู่กับที่นี่ไม่ได้อยู่ในโมดูลปัจจุบันมันยังไม่รู้จัก // คุณต้องพึ่งพาโมดูลที่เกี่ยวข้องในโมดูลปัจจุบันก่อน มันคล้ายกับตัวอย่างก่อนหน้า แต่ฉันไม่รู้ว่านี่เป็นวิธีที่ถูกต้องหรือไม่
myController. $ inject = ['$ scope', 'greeter'];
ควรระวังว่าคำสั่งของ $ inject จะต้องสอดคล้องกับคำสั่งของอาร์กิวเมนต์ที่ประกาศโดยฟังก์ชั่น
วิธีการอธิบายประกอบนี้มีประโยชน์สำหรับการประกาศคอนโทรลเลอร์เนื่องจากระบุข้อมูลคำอธิบายประกอบด้วยฟังก์ชั่น
3. คำอธิบายประกอบแบบอินไลน์ (ความคิดเห็นแบบอินไลน์)
บางครั้งมันไม่สะดวกที่จะใช้วิธีการเพิ่มความคิดเห็น $ inject เช่นเมื่อแสดงความคิดเห็นโดยตรง
ตัวอย่างเช่น:
somemodule.factory ('greeter', ฟังก์ชั่น ($ window) {... ;});เนื่องจากต้องใช้ตัวแปรชั่วคราว (ป้องกันไม่ให้ใช้งานหลังจากการบีบอัด) รหัสจะขยายตัวเป็น:
var greeterFactory = function (เปลี่ยนชื่อ $ window) {... ;}; greeterfactory. $ inject = ['$ window']; somemodule.factory ('greeter', greeterfactory);ด้วยเหตุนี้ (รหัส bloat) Angular จึงมีรูปแบบความคิดเห็นที่สาม:
somemodule.factory ('greeter', ['$ window', ฟังก์ชั่น (เปลี่ยนชื่อ $ หน้าต่าง) {... ;}]);โปรดจำไว้ว่ารูปแบบความคิดเห็นทั้งหมดนั้นเทียบเท่าและสามารถใช้งานได้ทุกที่ในเชิงมุมที่รองรับการฉีด
3. ฉันจะใช้ DI ได้ที่ไหน?
DI อยู่ทั่วเชิงมุม มันมักจะใช้ในคอนโทรลเลอร์และวิธีการจากโรงงาน
1. di ในคอนโทรลเลอร์
คอนโทรลเลอร์เป็นคลาสที่รับผิดชอบพฤติกรรมแอปพลิเคชัน (อธิบาย) วิธีการประกาศคอนโทรลเลอร์ที่แนะนำคือ:
var myController = function (dep1, dep2) {... } myController. $ inject = ['dep1', 'dep2']; myController.prototype.amethod = function () {... }2. วิธีการจากโรงงาน
วิธีการโรงงานมีหน้าที่สร้างวัตถุเชิงมุมส่วนใหญ่ ตัวอย่างเช่นคำสั่งบริการตัวกรอง วิธีการจากโรงงานลงทะเบียนในโมดูล วิธีการประกาศโรงงานที่แนะนำคือ:
angualar.module ('mymodule', []) config (['depprovider', ฟังก์ชั่น (depprovider) {... }]) Factory ('ServiceId', ['DepService', ฟังก์ชั่น (DepService) {... }]) Directive ('directivename', ['DepService', ฟังก์ชั่น (DepService) {... }]) ตัวกรอง ('filtername', ['depservice', ฟังก์ชั่น (depservice) {... }]);ข้างต้นเป็นบทสรุปของข้อมูลการฉีดพึ่งพา AngularJS ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!