การแนะนำ
หัวฉีดใช้ในการฉีดพารามิเตอร์อัตโนมัติเช่น
ฟังก์ชั่น fn ($ http, $ scope, aservice) {}เมื่อ NG ทำงาน, $ http, $ scope, aservice จะถูกส่งผ่านโดยอัตโนมัติเป็นพารามิเตอร์สำหรับการดำเนินการ
จริงๆแล้วมันง่ายที่จะคิดออกหัวฉีดทำสองสิ่ง
ซอร์สโค้ดต่อไปนี้วิเคราะห์วิธีการใช้สองสิ่งข้างต้น
โครงสร้าง
createInjector -> createInternalInjector return: instanceInjector
ดังนั้น createInjector () ส่งคืนอินสแตนซ์นิยายโครงสร้างมีดังนี้:
{revoke: revoke, industrial: standiate, get: getService, คำอธิบายประกอบ: คำอธิบายประกอบ, มี: function (ชื่อ) {return providercache.hasownproperty (ชื่อ + Providersuffix) || cache.hasownproperty (ชื่อ); -การวิเคราะห์ซอร์สโค้ด
1. CreateInjector
ฟังก์ชั่น createInjector (modulestoload, rigthdi) {rigthdi = (chartdi === true); var Instantiating = {}, providersuffix = 'ผู้ให้บริการ', path = [], loadedModules = new hashmap ([], true), // pre-configure $ ให้บริการลงทะเบียนการโทรใน LoadModules ฯลฯ ProviderCache = {$ ให้: {ผู้ให้บริการ SupportObject (ค่า), ค่าคงที่: SupportObject (ค่าคงที่), มัณฑนากร: Decorator}}, // ผู้ให้บริการ, อินสแตนซ์อินสแตนเตอร์สองหัวฉีด // อินสแตนซ์ให้บริการและการฉีดอื่น ๆ จากภายนอก "ผู้ให้บริการที่ไม่รู้จัก: {0}", path.join ('<-'));}, stractdi)), instancecache = {}, instanceinjector = (instancecache. $ injector = createInternalInjector InstanceInjector.invoke (ผู้ให้บริการ. $ get, ผู้ให้บริการ, ไม่ได้กำหนด, servicename); // การโหลดโมดูล foreach (loadmodules (modulestoload), ฟังก์ชั่น (fn) {instanceinjector.invoke (fn || noop);}); return instanceInjector;}2. $ ให้
$ PRIST: {ผู้ให้บริการ: SupportObject (ผู้ให้บริการ), โรงงาน: SupportObject (โรงงาน), บริการ: SupportObject (บริการ), ค่า: SupportObject (ค่า), ค่าคงที่: SupportObject (ค่าคงที่), มัณฑนากร: Decorator}2.1 SupportObject
สำหรับวิธีการบรรจุภัณฑ์วิธีการก่อนบรรจุภัณฑ์จะยอมรับพารามิเตอร์สองพารามิเตอร์ (คีย์ค่า) วิธีการแพคเกจสามารถรองรับพารามิเตอร์วัตถุที่ผ่านนั่นคือหลายปุ่ม -> ค่า
ฟังก์ชั่น supportObject (มอบหมาย) {return function (key, value) {ถ้า (isobject (key)) {foreach (คีย์, reversparams (มอบหมาย)); } else {return delegate (คีย์, ค่า); -2.2 ผู้ให้บริการ
ตรวจสอบวิธีการใช้ผู้ให้บริการบริการและโรงงาน
app.factory ('serviceName', function () {return {getName: function () {}, setName: function () {}}}); app.service ('serviceName', function () {this.getName = function () ฟังก์ชั่น ($ httpprovider) {// inject $ httpprovider this. $ get = function () {return {getName: function () {}, setName: function () {}};}}); app.provider ('serviceName' assertNothasOwnProperty (ชื่อ, 'บริการ'); // เมื่อผู้ให้บริการ _ คือ FN หรืออาร์เรย์ผู้ให้บริการรายอื่นสามารถฉีดเข้าไปในพารามิเตอร์ // เพราะเมื่อผู้ให้บริการนิติบุคคล (ผู้ให้บริการ _) สามารถส่งผ่านไปยังผู้ให้บริการรายอื่นที่ขึ้นอยู่กับ // นี่คือความแตกต่างระหว่างผู้ให้บริการและวิธีการที่ได้รับการพิสูจน์ } if (! ผู้ให้บริการ _. $ get) {โยน $ injectorminerr ('pget', "ผู้ให้บริการ '{0}' ต้องกำหนด $ get method โรงงาน", ชื่อ); } return ProviderCache [ชื่อ + Providersuffix] = ผู้ให้บริการ _;} ฟังก์ชั่นโรงงาน (ชื่อ, Factoryfn) {ผู้ให้บริการส่งคืน (ชื่อ, {$ get: Factoryfn}); } บริการฟังก์ชั่น (ชื่อ, ตัวสร้าง) {return Factory (ชื่อ, ['$ injector', ฟังก์ชั่น ($ injector) {return $ injector.instantiate (constructor);}]);} ค่าฟังก์ชัน (ชื่อ, val) {return Factory (ชื่อ, valuefn (val)); -ในที่สุดก็สรุปการดำเนินการของผู้ให้บริการแคชผู้ให้บริการไปยังผู้ให้บริการสำหรับการโทร
สิ่งที่แตกต่างจากคนอื่น ๆ คือการใช้งานค่าคงที่ซึ่งบันทึกไว้ใน ProviderCache และ Instancecache ตามลำดับเพื่อให้ทั้งผู้ให้บริการและบริการสามารถฉีดได้
ฟังก์ชั่นค่าคงที่ (ชื่อ, ค่า) {assertNothasOwnProperty (ชื่อ, 'คงที่'); ProviderCache [ชื่อ] = ค่า; Instancecache [ชื่อ] = value;}2.3 รีวิว loadmodules
ฟังก์ชั่น runinvokequeue (คิว) {var i, ii; สำหรับ (i = 0, ii = queue.length; i <ii; i ++) {var invokeargs = queue [i], provider = providerinjector.get (invokeargs [0]); // รูปแบบของคิวถูกเก็บไว้ใน [$ proves, โรงงาน, อาร์กิวเมนต์] // หลังจากการเปลี่ยนแล้ว, $ prost.Factory.apply ($ prost, อาร์กิวเมนต์); // มันคือการโทรไปที่ $ Provid Factory, บริการและผู้ให้บริการอื่น ๆ [Invokeargs [1]]. ใช้ (ผู้ให้บริการ, invokeargs [2]); -2.4 มัณฑนากร
ตัวอย่าง:
module.config (ฟังก์ชั่น ($ prost) {$ provists.decorator ('mail', function ($ delegate) {$ delegate.addcc = function (cc) {this.cc.push (cc);}; return $ delegate;});});การใช้ตัวอย่างจะเห็นได้ว่าพารามิเตอร์ที่ส่งผ่าน $ delegate เป็นอินสแตนซ์บริการดั้งเดิมและคุณต้องเพิ่มวิธีการในอินสแตนซ์นี้
ซอร์สโค้ด:
ฟังก์ชั่นมัณฑนากร (serviceName, decorfn) {var origprovider = providerInjector.get (serviceName + Providersuffix), Orig $ get = Origprovider. $ get; Origprovider. $ get = function () {// สร้างอินสแตนซ์บริการที่ต้องการผ่านผู้ให้บริการที่ได้รับข้างต้นและฉีดลงในรายการพารามิเตอร์ด้วย $ delegate var originstance = instanceInjector.invoke (Orig $ get, Origprovider); Return InstanceInjector.invoke (Decorfn, Null, {$ Delegate: Originstance}); -3. CreateInternalInjector
3.1 โครงสร้างโดยรวม
// รับจากแคชถ้าไม่เรียกโรงงานเพื่อสร้าง ดูการวิเคราะห์ GetService สำหรับรายละเอียด
ฟังก์ชั่น createinternalInjector (แคช, โรงงาน) {ฟังก์ชั่น getService (serviceName) {} function revoke (fn, self, locals, serviceName) {} ฟังก์ชั่นอินสแตนซ์ (ประเภท, locals, servicename) {} return {// execute fn รายการพารามิเตอร์ของวิธีการสำหรับคำอธิบายประกอบการฉีด: คำอธิบายประกอบ, // ยืนยันว่ามีผู้ให้บริการหรือบริการมี: ฟังก์ชั่น (ชื่อ) {ส่งคืนผู้ให้บริการ cache.hasownproperty (ชื่อ + ผู้ให้บริการ) || cache.hasownproperty (ชื่อ); -3.2 คำอธิบายประกอบ
รับรายการพารามิเตอร์ของ FN
// type1function fn (a, b, c) -> ['a', 'b', 'c'] // type2 ['a', 'b', fn] -> ['a', 'b'] // type3function fn () {} fn. $ inject = ['a', 'c'ซอร์สโค้ด:
ฟังก์ชั่นคำอธิบายประกอบ (fn, chartdi, ชื่อ) {var $ inject, fntext, argdecl, สุดท้าย; if (typeof fn === 'function') {ถ้า (! ($ inject = fn. $ inject)) {$ inject = []; if (fn.length) {// ถ้า (stuppledi) {ถ้า (! isstring (ชื่อ) ||! ชื่อ) {name = fn.name || anonfn (fn); } โยน $ injectorminerr ('rigthdi', '{0} ไม่ได้ใช้คำอธิบายประกอบที่ชัดเจนและไม่สามารถเรียกใช้ในโหมดที่เข้มงวด' ชื่อ); } // ลบความคิดเห็น fntext = fn.toString (). แทนที่ (strip_comments, ''); // เลือกพารามิเตอร์ทั้งหมด fn (a, b, c, d) -> 'a, b, c, d' argdecl = fntext.match (fn_args); // แบ่งออกเป็น array foreach (argdecl [1] .split (fn_arg_split), ฟังก์ชั่น (arg) {arg.replace (fn_arg, ฟังก์ชั่น (ทั้งหมด, ขีดล่าง, ชื่อ) {$ inject.push (ชื่อ);});}); - } fn. $ inject = $ inject; }} อื่นถ้า (isarray (fn)) {last = fn.length - 1; assertargfn (fn [สุดท้าย], 'fn'); $ inject = fn.slice (0, สุดท้าย); } else {assertArgfn (fn, 'fn', true); } return $ inject;}3.3 GetService
// เมื่อไม่มีบริการในแคชป้อนอื่นแคช [servicename] = อินสแตนซ์เพื่อทำเครื่องหมาย // เพราะการโทรครั้งต่อไป (serviceName) มันเป็นจริงเรียกใช้ซ้ำ // ฟังก์ชั่น (servicename) {// varider. ServiceName); //} // instanceinjector.invoke (ผู้ให้บริการ. $ รับจะออกพารามิเตอร์ที่ต้องฉีดและฉีด // ดังนั้นหลังจากทำเครื่องหมายแล้วคุณสามารถตรวจสอบได้ว่ามีฟังก์ชั่นการพึ่งพาเป็นวงกลม $ injectorminerr ('cdep', 'การพึ่งพาอาศัยกันเป็นวงกลม: {0}', servicename + '<-' + path.join ('<-'); {if (cache [servicename] === อินสแตนซ์) {ลบแคช [servicename];3.4 เรียก
ฟังก์ชั่นเรียกใช้ (fn, self, locals, serviceName) {ถ้า (typeof locals === 'string') {serviceName = locals; คนในท้องถิ่น = null; } var args = [], // รับรายการพารามิเตอร์ $ inject = คำอธิบายประกอบ (fn, chartdi, serviceName), ความยาว, i, คีย์; สำหรับ (i = 0, length = $ inject.length; i <length; i ++) {key = $ inject [i]; if (key typeof! == 'string') {โยน $ injectorminerr ('itkn', 'โทเค็นการฉีดที่ไม่ถูกต้อง! ชื่อบริการที่คาดหวังเป็นสตริงได้รับ {0}', คีย์); } // locals priority args.push (locals && locals.hasownproperty (คีย์)? locals [key]: getService (คีย์)); } if (isarray (fn)) {fn = fn [ความยาว]; } return fn.apply (self, args);}3.5 อินสแตนซ์
ฟังก์ชั่นอินสแตนซ์ (ประเภท, locals, serviceName) {var constructor = function () {}, อินสแตนซ์, returnvalue; // เมื่อประเภทคืออาร์เรย์รับพารามิเตอร์สุดท้ายเช่น: ['$ window', ฟังก์ชั่น ($ win) {}] constructor.prototype = (isarray (type)? type [type.length - 1]: type) .prototype; อินสแตนซ์ = ตัวสร้างใหม่ (); // การเรียกเรียกใช้เพื่อเรียกใช้วิธีการพิมพ์ returnvalue = revoke (ประเภท, อินสแตนซ์, ท้องถิ่น, servicename); return isobject (returnvalue) || isfunction (returnedValue)? ReturnedValue: อินสแตนซ์;}ฟังก์ชั่นของอินสแตนซ์คือการสร้างอินสแตนซ์ประเภทและพารามิเตอร์สามารถส่งผ่านไปยังตัวสร้างโดยอัตโนมัติในระหว่างกระบวนการอินสแตนซ์