แทนที่จะกรอกตารางด้วย "ใช่" และ "ไม่" โดยไม่มีคำอธิบายฉันจะพูดถึงรายละเอียดเพิ่มเติมเล็กน้อย
[หมายเหตุเพิ่มหลังจากเสร็จสิ้น: สิ่งนี้จบลงแล้ว ... นานกว่าที่ฉันคาดไว้สักหน่อย มี 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
ฟังก์ชั่นความหมาย)
เนื่องจากconstant
s และvalue
s ส่งคืนค่าสแตติกเสมอพวกมันจะไม่ถูกเรียกผ่านหัวฉีดดังนั้นคุณจึงไม่สามารถฉีดด้วยสิ่งใดก็ได้
การกำหนดค่าผู้ให้บริการ
คุณอาจจะสงสัยว่าทำไมทุกคนจะรำคาญที่จะตั้งขึ้นเป็นผู้ให้บริการที่เต็มเปี่ยมด้วย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!
});
มีข้อยกเว้นที่สำคัญข้อหนึ่ง: constant
s เนื่องจากพวกเขาไม่สามารถเปลี่ยนแปลงได้จึงได้รับอนุญาตให้ฉีดเข้าไปภายในconfig
บล็อก (นี่คือความแตกต่างจากvalue
s) พวกเขาเข้าถึงได้โดยใช้ชื่อของตนเองเพียงอย่างเดียว (ไม่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
ความแตกต่างที่ระบุไว้ในที่นี้)