แทนที่จะกรอกตารางด้วย "ใช่" และ "ไม่" โดยไม่มีคำอธิบายฉันจะพูดถึงรายละเอียดเพิ่มเติมเล็กน้อย
[หมายเหตุเพิ่มหลังจากเสร็จสิ้น: สิ่งนี้จบลงแล้ว ... นานกว่าที่ฉันคาดไว้สักหน่อย มี tl; dr ที่ด้านล่าง แต่ฉันหวังว่านี่จะเป็นข้อมูลให้]
[คำตอบนี้ถูกเพิ่มไปยังวิกิ AngularJS: การทำความเข้าใจการพึ่งพาการฉีด ]
$provideบริการเป็นผู้รับผิดชอบบอกเชิงมุมวิธีการสร้างสิ่งฉีดใหม่ สิ่งเหล่านี้จะเรียกว่าบริการ บริการจะถูกกำหนดโดยสิ่งที่เรียกว่าผู้ให้บริการ$provideซึ่งเป็นสิ่งที่คุณกำลังสร้างเมื่อคุณใช้ การกำหนดผู้ให้บริการจะทำผ่านproviderวิธีการในการ$provideบริการและคุณสามารถรับ$provideบริการโดยขอให้มันถูกฉีดเข้าไปในconfigฟังก์ชั่นการใช้งานของ ตัวอย่างอาจเป็นดังนี้:
app.config(function($provide) {
$provide.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
});
ที่นี่เราได้กำหนดไว้ให้บริการใหม่สำหรับบริการที่เรียกว่าgreeting; เราสามารถฉีดตัวแปรที่มีชื่อgreetingลงในฟังก์ชั่นการฉีดใด ๆ (เช่นตัวควบคุมเพิ่มเติมในภายหลัง) และ Angular จะเรียกใช้$getฟังก์ชันของผู้ให้บริการเพื่อส่งคืนอินสแตนซ์ใหม่ของบริการ ในกรณีนี้สิ่งที่จะถูกฉีดคือฟังก์ชันที่รับnameพารามิเตอร์และalertข้อความ sa ตามชื่อ เราอาจใช้สิ่งนี้:
app.controller('MainController', function($scope, greeting) {
$scope.onClick = function() {
greeting('Ford Prefect');
};
});
นี่คือเคล็ดลับ factory, serviceและvalueเป็นเพียงทางลัดเพื่อกำหนดส่วนต่าง ๆ ของผู้ให้บริการ - นั่นคือพวกเขามีวิธีการกำหนดผู้ให้บริการโดยไม่ต้องพิมพ์สิ่งที่ออกทั้งหมด ตัวอย่างเช่นคุณสามารถเขียนผู้ให้บริการรายเดียวกันนั้นได้เช่นนี้
app.config(function($provide) {
$provide.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
});
สิ่งสำคัญคือต้องเข้าใจดังนั้นฉันจะใช้ถ้อยคำใหม่: ภายใต้ประทุน AngularJS กำลังเรียกใช้รหัสเดียวกันกับที่เราเขียนไว้ด้านบน ( $provide.providerฉบับ) สำหรับเรา แท้จริงแล้วไม่มีความแตกต่างในสองเวอร์ชั่นนี้ 100% valueทำงานเพียงวิธีเดียว - ถ้าสิ่งที่เราจะกลับมาจากการที่เรา$getฟังก์ชั่น (aka ของเราfactoryฟังก์ชั่น) valueอยู่เสมอเหมือนกันเราสามารถเขียนโค้ดแม้แต่น้อยโดยใช้ ตัวอย่างเช่นเนื่องจากเราส่งคืนฟังก์ชันเดียวกันสำหรับgreetingบริการของเราเราจึงสามารถใช้valueเพื่อกำหนดได้เช่นกัน:
app.config(function($provide) {
$provide.value('greeting', function(name) {
alert("Hello, " + name);
});
});
อีกครั้งนี่เป็น 100% เหมือนกันกับอีกสองวิธีที่เราเคยใช้เพื่อกำหนดฟังก์ชั่นนี้ - มันเป็นวิธีหนึ่งในการบันทึกการพิมพ์
ตอนนี้คุณอาจสังเกตเห็นapp.config(function($provide) { ... })สิ่งที่น่ารำคาญที่ฉันใช้อยู่ เนื่องจากการกำหนดผู้ให้บริการใหม่ (ผ่านวิธีการใด ๆที่ระบุด้านบน) เป็นเรื่องธรรมดา AngularJS จะเปิดเผย$providerวิธีการโดยตรงบนวัตถุโมดูลเพื่อประหยัดการพิมพ์มากยิ่งขึ้น:
var myMod = angular.module('myModule', []);
myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);
สิ่งเหล่านี้ทำในสิ่งเดียวกันกับapp.config(...)เวอร์ชั่นที่เราใช้มาก่อนหน้านี้
constantที่ผมเคยฉีดหนึ่งข้ามเพื่อให้ห่างไกล valueสำหรับตอนนี้ก็พอง่ายที่จะพูดว่ามันทำงานเช่นเดียวกับ เราจะเห็นว่ามีข้อแตกต่างในภายหลัง
ในการตรวจสอบ , ทุกชิ้นส่วนเหล่านี้ของรหัสที่กำลังทำที่แน่นอนสิ่งเดียวกัน
myMod.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
myMod.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
myMod.value('greeting', function(name) {
alert("Hello, " + name);
});
หัวฉีดเป็นผู้รับผิดชอบจริงการสร้างอินสแตนซ์ของการบริการของเราโดยใช้โค้ดที่เราให้ผ่าน$provide(ไม่มีเล่นสำนวนเจตนา) เมื่อใดก็ตามที่คุณเขียนฟังก์ชั่นที่รับการโต้เถียงคุณจะเห็นหัวฉีดในที่ทำงาน แต่ละแอปพลิเคชัน AngularJS มีซิงเกิ้ล$injectorที่สร้างขึ้นเมื่อแอปพลิเคชันเริ่มต้นครั้งแรก คุณสามารถจับมันได้โดยการฉีด$injectorเข้าไปในฟังก์ชั่นการฉีด (ใช่$injectorรู้วิธีฉีดเอง!)
เมื่อคุณมี$injectorแล้วคุณจะได้รับอินสแตนซ์ของบริการที่กำหนดโดยเรียกใช้บริการgetพร้อมชื่อบริการ ตัวอย่างเช่น,
var greeting = $injector.get('greeting');
greeting('Ford Prefect');
หัวฉีดยังรับผิดชอบในการฉีดบริการลงในฟังก์ชั่น; ตัวอย่างเช่นคุณสามารถฉีดบริการลงในฟังก์ชันใด ๆ ที่คุณใช้invokeวิธีการของหัวฉีดได้อย่างน่าอัศจรรย์
var myFunction = function(greeting) {
greeting('Ford Prefect');
};
$injector.invoke(myFunction);
คุ้มค่าสังเกตว่าหัวฉีดเท่านั้นที่จะสร้างตัวอย่างของบริการที่ใช้งานครั้งเดียว จากนั้นจะแคชสิ่งใดก็ตามที่ผู้ให้บริการส่งคืนโดยใช้ชื่อของบริการ ครั้งต่อไปที่คุณขอใช้บริการคุณจะได้รับวัตถุเดียวกันแน่นอน
ดังนั้นเพื่อตอบคำถามของคุณคุณสามารถฉีดบริการเข้าสู่ฟังก์ชั่นใด ๆ $injector.invokeที่เรียกว่ามี ซึ่งรวมถึง
- ฟังก์ชันนิยามคอนโทรลเลอร์
- ฟังก์ชันการกำหนดคำสั่ง
- ฟังก์ชันนิยามตัวกรอง
$getวิธีการของผู้ให้บริการ (aka factoryฟังก์ชั่นความหมาย)
เนื่องจากconstants และvalues ส่งคืนค่าสแตติกเสมอพวกมันจะไม่ถูกเรียกผ่านหัวฉีดดังนั้นคุณจึงไม่สามารถฉีดด้วยสิ่งใดก็ได้
การกำหนดค่าผู้ให้บริการ
คุณอาจจะสงสัยว่าทำไมทุกคนจะรำคาญที่จะตั้งขึ้นเป็นผู้ให้บริการที่เต็มเปี่ยมด้วยprovideวิธีถ้าfactory, valueฯลฯ มากขึ้น คำตอบคือผู้ให้บริการอนุญาตการกำหนดค่าจำนวนมาก เราได้กล่าวแล้วว่าเมื่อคุณสร้างบริการผ่านผู้ให้บริการ (หรือทางลัดใด ๆ ที่ Angular มอบให้คุณ) คุณจะสร้างผู้ให้บริการใหม่ที่กำหนดวิธีการสร้างบริการนั้น สิ่งที่ฉันไม่ได้กล่าวถึงคือผู้ให้บริการเหล่านี้สามารถแทรกลงในconfigส่วนของแอปพลิเคชันของคุณเพื่อให้คุณสามารถโต้ตอบกับพวกเขาได้!
อันดับแรกแองกูลาร์รันแอปพลิเคชันของคุณในสองเฟส - configและrunเฟส configขั้นตอนที่เราได้เห็นเป็นที่ที่คุณสามารถตั้งค่าให้บริการใด ๆ ตามความจำเป็น นี่คือจุดที่คำสั่งตัวควบคุมตัวกรองและสิ่งที่คล้ายกัน runเฟสที่คุณอาจจะคิดว่าเป็นที่ที่เชิงมุมจริงรวบรวม DOM ของคุณและเริ่มต้นขึ้นของแอป
คุณสามารถเพิ่มรหัสเพิ่มเติมที่จะทำงานในขั้นตอนเหล่านี้ด้วยmyMod.configและmyMod.runฟังก์ชั่น - แต่ละฟังก์ชั่นที่จะทำงานในช่วงที่เฉพาะเจาะจง ดังที่เราเห็นในส่วนแรกฟังก์ชั่นเหล่านี้สามารถฉีดได้ - เราฉีด$provideบริการที่มีอยู่แล้วในตัวอย่างโค้ดแรกของเรา อย่างไรก็ตามสิ่งที่น่าสังเกตคือในconfigช่วงนี้มีเพียงผู้ให้บริการเท่านั้นที่สามารถทำการฉีด (ยกเว้นบริการในAUTOโมดูล - $provideและ$injector)
ตัวอย่างเช่นสิ่งต่อไปนี้ไม่ได้รับอนุญาต :
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
สิ่งที่คุณทำมีการเข้าถึงผู้ใดเป็นผู้ให้บริการสำหรับการให้บริการที่คุณได้ทำ:
myMod.config(function(greetingProvider) {
// a-ok!
});
มีข้อยกเว้นที่สำคัญข้อหนึ่ง: constants เนื่องจากพวกเขาไม่สามารถเปลี่ยนแปลงได้จึงได้รับอนุญาตให้ฉีดเข้าไปภายในconfigบล็อก (นี่คือความแตกต่างจากvalues) พวกเขาเข้าถึงได้โดยใช้ชื่อของตนเองเพียงอย่างเดียว (ไม่Providerจำเป็นต้องใส่คำต่อท้าย)
เมื่อใดก็ตามที่คุณกำหนดผู้ให้บริการสำหรับบริการผู้ให้บริการนั้นจะได้รับการตั้งชื่อserviceProviderโดยserviceเป็นชื่อของบริการ ตอนนี้เราสามารถใช้พลังของผู้ให้บริการทำสิ่งที่ซับซ้อนมากขึ้น!
myMod.provider('greeting', function() {
var text = 'Hello, ';
this.setText = function(value) {
text = value;
};
this.$get = function() {
return function(name) {
alert(text + name);
};
};
});
myMod.config(function(greetingProvider) {
greetingProvider.setText("Howdy there, ");
});
myMod.run(function(greeting) {
greeting('Ford Prefect');
});
ตอนนี้เรามีฟังก์ชั่นกับผู้ให้บริการของเราที่เรียกsetTextว่าเราสามารถใช้ในการปรับแต่งของเราalert ; เราสามารถเข้าถึงผู้ให้บริการรายนี้ในconfigบล็อกเพื่อเรียกใช้วิธีนี้และปรับแต่งบริการ เมื่อเรารันแอพของเราในที่สุดเราสามารถคว้าgreetingบริการและลองใช้งานเพื่อดูว่าการปรับแต่งของเรามีผล
เนื่องจากนี่เป็นตัวอย่างที่ซับซ้อนมากขึ้นต่อไปนี้เป็นการสาธิตการทำงาน: http://jsfiddle.net/BinaryMuse/9GjYg/
สามารถฉีดฟังก์ชั่นของคอนโทรลเลอร์ได้ แต่ตัวควบคุมจะไม่สามารถฉีดเข้าไปในสิ่งอื่นได้ นั่นเป็นเพราะตัวควบคุมไม่ได้ถูกสร้างผ่านผู้ให้บริการ แต่มีบริการ Angular ในตัว$controllerที่เรียกว่ารับผิดชอบการตั้งค่าตัวควบคุมของคุณ เมื่อคุณโทรmyMod.controller(...)คุณกำลังเข้าถึงผู้ให้บริการนี้จริง ๆเหมือนกับในส่วนสุดท้าย
ตัวอย่างเช่นเมื่อคุณกำหนดคอนโทรลเลอร์เช่นนี้:
myMod.controller('MainController', function($scope) {
// ...
});
สิ่งที่คุณทำจริงๆคือ:
myMod.config(function($controllerProvider) {
$controllerProvider.register('MainController', function($scope) {
// ...
});
});
ต่อมาเมื่อ Angular ต้องการสร้างอินสแตนซ์ของคอนโทรลเลอร์ของคุณมันจะใช้$controllerบริการ (ซึ่งจะใช้ใน$injectorการเรียกใช้ฟังก์ชั่นคอนโทรลเลอร์ของคุณ
ตัวกรองและคำสั่ง
filterและdirectiveทำงานในลักษณะเดียวกับcontroller; filterใช้บริการที่เรียกว่า$filterและผู้ให้บริการ$filterProviderในขณะที่directiveการใช้บริการที่เรียกว่าและผู้ให้บริการของตน$compile $compileProviderลิงค์บางส่วน:
ตามตัวอย่างอื่น ๆmyMod.filterและmyMod.directiveเป็นทางลัดในการกำหนดค่าบริการเหล่านี้

ดังนั้นเพื่อสรุปการทำงานใด ๆ ที่ได้รับการเรียกว่ามีสามารถฉีดเข้าไป$injector.invoke ซึ่งรวมถึงจากแผนภูมิของคุณ (แต่ไม่ จำกัด เฉพาะ):
- ตัวควบคุม
- คำสั่ง
- โรงงาน
- กรอง
- ผู้ให้บริการ
$get(เมื่อกำหนดผู้ให้บริการเป็นวัตถุ)
- ฟังก์ชั่นผู้ให้บริการ (เมื่อกำหนดผู้ให้บริการเป็นฟังก์ชั่นคอนสตรัค)
- บริการ
ผู้ให้บริการสร้างบริการใหม่ที่สามารถฉีดเข้าไปในสิ่งต่างๆ รวมถึง:
- คงที่
- โรงงาน
- ผู้ให้บริการ
- บริการ
- ความคุ้มค่า
ที่กล่าวว่าบริการในตัวเช่น$controllerและ$filter สามารถฉีดและคุณสามารถใช้บริการเหล่านั้นเพื่อระงับตัวกรองและตัวควบคุมใหม่ที่คุณกำหนดด้วยวิธีการเหล่านั้น (แม้ว่าสิ่งที่คุณกำหนดจะไม่สามารถทำได้ด้วยตนเอง ฉีดเข้าไปในสิ่งต่าง ๆ )
นอกเหนือจากนั้นฟังก์ชั่นใด ๆ ที่เรียกใช้หัวฉีดสามารถถูกฉีดเข้ากับบริการที่ผู้ให้บริการกำหนดไว้ - ไม่มีข้อ จำกัด (นอกเหนือจากconfigและrunความแตกต่างที่ระบุไว้ในที่นี้)