ในการพัฒนาโครงการเชิงมุม เรามักจะใช้การเชื่อมโยงคุณสมบัติอินพุตและการเชื่อมโยงเหตุการณ์เอาท์พุตสำหรับการสื่อสารส่วนประกอบ อย่างไรก็ตาม อินพุตและเอาท์พุตสามารถใช้ได้ในพาเรนต์-ไชด์เท่านั้น ส่วนประกอบการส่งข้อมูล ส่วนประกอบต่างๆ จะสร้างแผนผังส่วนประกอบตามความสัมพันธ์ในการเรียก หากมีเพียงการเชื่อมโยงคุณสมบัติและการเชื่อมโยงเหตุการณ์ ส่วนประกอบความสัมพันธ์ที่ไม่ใช่โดยตรงทั้งสองจะต้องสื่อสารผ่านจุดเชื่อมต่อแต่ละจุดเอง คนกลางจำเป็นต้องประมวลผลอย่างต่อเนื่องและส่งผ่านบางสิ่งที่ทำ ไม่จำเป็นต้องรู้ข้อมูล (รูปที่ 1 เหลือ) Injectable Service ที่ให้ไว้ใน Angular สามารถให้บริการได้ในโมดูล ส่วนประกอบ หรือคำสั่ง และเมื่อรวมกับการฉีดใน Constructor ก็สามารถแก้ปัญหานี้ได้ (ในรูปที่ 1) [บทช่วยสอนที่เกี่ยวข้องที่แนะนำ: "บทช่วยสอนเชิงมุม"]
รูปที่ 1 โมเดลการสื่อสารแบบคอมโพเนนต์
รูปภาพด้านซ้ายส่งข้อมูลผ่านคอมโพเนนต์พาเรนต์-ไชด์เท่านั้น โหนด a และโหนด b จำเป็นต้องผ่านหลายโหนดเพื่อสื่อสาร หากโหนด c ต้องการควบคุมโหนด b ผ่านการกำหนดค่าบางอย่าง โหนดระหว่างโหนดเหล่านั้นจะต้องตั้งค่าด้วย คุณลักษณะหรือเหตุการณ์เพิ่มเติมเพื่อส่งข้อมูลที่เกี่ยวข้องอย่างโปร่งใส โหนดโหมดการพึ่งพา c ในภาพด้านขวาสามารถให้บริการสำหรับโหนด a และ b เพื่อสื่อสารได้ โหนด a สื่อสารโดยตรงกับบริการที่จัดทำโดยโหนด c และโหนด b ยังสื่อสารโดยตรงกับบริการที่มอบให้โดยโหนด c ในที่สุด การสื่อสารก็ง่ายขึ้น และโหนดตรงกลางไม่ได้เชื่อมโยงกับส่วนนี้ของเนื้อหา และไม่มีการรับรู้ที่ชัดเจนถึงการสื่อสารที่เกิดขึ้นระหว่างส่วนประกอบบนและล่าง
การพึ่งพาการฉีด (DI) ไม่ใช่ลักษณะเฉพาะของแองกูลาร์ มันเป็นวิธีในการใช้รูปแบบการออกแบบการผกผันของการควบคุม (IOC) การเกิดขึ้นของการฉีดการพึ่งพาช่วยแก้ปัญหาการมีเพศสัมพันธ์มากเกินไป การสร้างอินสแตนซ์และทรัพยากรทั้งหมดไม่สามารถนำมาใช้ได้ การจัดการทรัพยากรโดยทั้งสองฝ่าย แทนที่จะได้รับจากศูนย์ทรัพยากรหรือบุคคลที่สามที่ไม่ได้ใช้ทรัพยากร สามารถก่อให้เกิดประโยชน์มากมาย ประการแรก การจัดการทรัพยากรแบบรวมศูนย์ทำให้สามารถกำหนดค่าทรัพยากรและจัดการได้ง่าย ประการที่สอง ลดระดับการพึ่งพาระหว่างทั้งสองฝ่ายโดยใช้ทรัพยากร ซึ่งเราเรียกว่าการมีเพศสัมพันธ์
ความคล้ายคลึงกับโลกแห่งความเป็นจริงคือเมื่อเราซื้อผลิตภัณฑ์เช่นดินสอ เราเพียงแต่ต้องหาร้านค้าเพื่อซื้อผลิตภัณฑ์ประเภทดินสอเท่านั้น เราไม่สนใจว่าดินสอนั้นผลิตที่ไหนหรือไม้และไส้ดินสอเป็นอย่างไร ถูกผูกมัด เราเพียงต้องการมันเพื่อทำหน้าที่เขียนของดินสอให้สมบูรณ์ เราจะไม่มีการติดต่อกับผู้ผลิตหรือโรงงานที่เฉพาะเจาะจง สำหรับร้านค้านั้นสามารถซื้อดินสอได้จากช่องทางที่เหมาะสมและตระหนักถึงความสามารถในการกำหนดค่าของทรัพยากร
เมื่อรวมกับสถานการณ์การเข้ารหัส ผู้ใช้ไม่จำเป็นต้องสร้างอินสแตนซ์อย่างชัดเจน (การดำเนินการใหม่) เพื่อแทรกและใช้อินสแตนซ์ การสร้างอินสแตนซ์จะถูกกำหนดโดยผู้ให้บริการ การจัดการทรัพยากรทำได้ผ่านโทเค็น เนื่องจากไม่สนใจผู้ให้บริการหรือการสร้างอินสแตนซ์ ผู้ใช้จึงสามารถใช้วิธีการฉีดในเครื่องบางวิธี (การกำหนดค่าโทเค็นรอง) เพื่อให้บรรลุการแทนที่อินสแตนซ์และโหมดการขึ้นต่อกันในท้ายที่สุด ) เติมเต็มซึ่งกันและกัน
เป็นหนึ่งในโมดูลหลักที่สำคัญที่สุดของกรอบงาน Angular ไม่เพียงแต่ให้การฉีดประเภทบริการเท่านั้น แต่แผนผังส่วนประกอบเองก็เป็นแผนผังการพึ่งพาการฉีดและยังสามารถฉีดฟังก์ชันและค่าได้อีกด้วย กล่าวคือ ในเฟรมเวิร์ก Angular คอมโพเนนต์ย่อยสามารถแทรกอินสแตนซ์คอมโพเนนต์พาเรนต์ผ่านโทเค็นของคอมโพเนนต์พาเรนต์ (โดยปกติจะเป็นชื่อคลาส) ในการพัฒนาไลบรารีส่วนประกอบ มีหลายกรณีที่การโต้ตอบและการสื่อสารทำได้โดยการฉีดส่วนประกอบหลัก รวมถึงการติดตั้งพารามิเตอร์ การแบ่งปันสถานะ และแม้กระทั่งการได้รับ DOM ของโหนดที่มีส่วนประกอบหลักอยู่ เป็นต้น
หากต้องการใช้ Angular Injection คุณต้องเข้าใจกระบวนการแก้ปัญหาในการฉีดก่อน เช่นเดียวกับกระบวนการแยกวิเคราะห์ของ node_modules เมื่อไม่พบการขึ้นต่อกัน การขึ้นต่อกันนั้นจะแสดงขึ้นที่เลเยอร์พาเรนต์เสมอเพื่อค้นหาการขึ้นต่อกัน Angular เวอร์ชันเก่า (ก่อน v6) แบ่งกระบวนการแยกวิเคราะห์การฉีดออกเป็นโมดูลหัวฉีดหลายระดับ หัวฉีดส่วนประกอบหลายระดับ และหัวฉีดองค์ประกอบ เวอร์ชันใหม่ (หลัง v9) ถูกทำให้ง่ายขึ้นเป็นโมเดลสองระดับ สายการสืบค้นแรกคือตัวฉีดองค์ประกอบระดับ DOM แบบคงที่ ฯลฯ เรียกรวมกันว่าตัวฉีดองค์ประกอบ และสายการสืบค้นอีกสายคือตัวฉีดโมดูล ลำดับการแยกวิเคราะห์และค่าเริ่มต้นหลังการแยกวิเคราะห์ล้มเหลวจะมีการอธิบายให้ชัดเจนยิ่งขึ้นในเอกสารความคิดเห็นเกี่ยวกับโค้ดอย่างเป็นทางการ (provider_flag)
รูปที่ 2 กระบวนการค้นหาการขึ้นต่อกันของหัวฉีดสองระดับ (แหล่งรูปภาพ)
หมายความว่าส่วนประกอบ/คำแนะนำและการจัดเตรียมเนื้อหาที่ฉีดในระดับส่วนประกอบ/คำสั่งจะค้นหาการขึ้นต่อกันในองค์ประกอบในมุมมองส่วนประกอบไปจนถึงองค์ประกอบรูทก่อน หากไม่พบ การอ้างอิง (รวมถึงการอ้างอิงโมดูลและการอ้างอิงการโหลดแบบ Lazy Loading) ในองค์ประกอบ The current module จะถูกค้นหาจนถึงโมดูลรูทและโมดูลแพลตฟอร์ม
โปรดทราบว่าหัวฉีดที่นี่มีการสืบทอด องค์ประกอบ injector สามารถสร้างและสืบทอดฟังก์ชันการค้นหาของ injector ขององค์ประกอบหลักได้ และโมดูล injector ก็คล้ายกัน หลังจากการสืบทอดอย่างต่อเนื่อง มันจะกลายเป็นเหมือนห่วงโซ่ต้นแบบของอ็อบเจ็กต์ js
เข้าใจลำดับความสำคัญของการแก้ปัญหาการพึ่งพา และเราสามารถจัดเตรียมเนื้อหาในระดับที่เหมาะสมได้ เรารู้แล้วว่ามีสองประเภท: การแทรกโมดูลและการแทรกองค์ประกอบ
โมดูลอินเจคเตอร์: ผู้ให้บริการสามารถกำหนดค่าได้ในแอตทริบิวต์ข้อมูลเมตาของ @NgModule และคุณยังสามารถใช้คำสั่ง @Injectable ที่ให้ไว้หลังจาก v6 ได้ ProvideIn ได้รับการประกาศเป็นชื่อโมดูล 'root' ฯลฯ (อันที่จริง มีหัวฉีดสองตัวอยู่เหนือโมดูลรูท นั่นคือ Platform และ Null ซึ่งจะไม่มีการกล่าวถึงที่นี่)
องค์ประกอบ injector: ผู้ให้บริการ, viewProviders สามารถกำหนดค่าได้ในแอตทริบิวต์ข้อมูลเมตาของส่วนประกอบ @Component หรือใน @ ของคำสั่ง ผู้ให้บริการในเมตาดาต้าของคำสั่ง
นอกจากนี้ ในความเป็นจริง นอกเหนือจากการใช้โมดูลหัวฉีดที่ประกาศแล้ว @Injectable มัณฑนากรยังสามารถประกาศให้เป็นองค์ประกอบหัวฉีดได้อีกด้วย บ่อยกว่านั้นจะมีการประกาศว่ามีให้ที่รูทเพื่อใช้งานซิงเกิลตัน มันรวมข้อมูลเมตาผ่านคลาสเองเพื่อหลีกเลี่ยงโมดูลหรือส่วนประกอบที่ประกาศผู้ให้บริการโดยตรง ด้วยวิธีนี้ หากคลาสไม่มีบริการคำสั่งส่วนประกอบใด ๆ และคลาสอื่น ๆ ที่จะแทรก จะไม่มีรหัสเชื่อมโยงกับการประกาศประเภทและ คอมไพเลอร์สามารถละเลยได้ จึงบรรลุ Shake the tree
อีกวิธีหนึ่งในการระบุคือการให้ค่าโดยตรงเมื่อประกาศฉีดToken
นี่คือเทมเพลตชวเลขสำหรับวิธีการเหล่านี้:
@NgModule({ ผู้ให้บริการ: [ // โมดูลหัวฉีด] - ส่งออกคลาส MyModule {}
@Component ({ ผู้ให้บริการ: [ // องค์ประกอบหัวฉีด - ส่วนประกอบ], ดูผู้ให้บริการ: [ // องค์ประกอบหัวฉีด - มุมมองส่วนประกอบ] - ส่งออกคลาส MyComponent {}
@Directive ({ ผู้ให้บริการ: [ // องค์ประกอบหัวฉีด - คำสั่ง] - ส่งออกคลาส MyDirective {}
@Injectable ({ ให้ไว้ใน: 'ราก' - ส่งออกคลาส MyService {}
ส่งออก const MY_INJECT_TOKEN = new InjectionToken<MyClass>('my-inject-token', { ให้ไว้ใน: 'ราก' โรงงาน: () => { กลับ MyClass ใหม่ (); - });
ตัวเลือกต่างๆ สำหรับการระบุตำแหน่งการขึ้นต่อกันจะนำมาซึ่งความแตกต่างบางประการ ซึ่งท้ายที่สุดจะส่งผลต่อขนาดของแพ็คเกจ ขอบเขตที่สามารถแทรกการขึ้นต่อกัน และวงจรชีวิตของการขึ้นต่อกัน มีวิธีแก้ไขปัญหาที่แตกต่างกันออกไปสำหรับสถานการณ์ที่แตกต่างกัน เช่น ซิงเกิลตัน (รูท) การแยกบริการ (โมดูล) หน้าต่างการแก้ไขหลายรายการ (ส่วนประกอบ) ฯลฯ คุณควรเลือกตำแหน่งที่เหมาะสมเพื่อหลีกเลี่ยงข้อมูลที่แชร์ที่ไม่เหมาะสมหรือการบรรจุโค้ดที่ซ้ำซ้อน
มีเพียงการแทรกอินสแตนซ์เท่านั้น เครื่องมือนั้นจะไม่แสดงความยืดหยุ่นของการพึ่งพาการแทรกของกรอบงาน Angular Angular มีเครื่องมือการฉีดที่ยืดหยุ่นมากมาย useClass จะสร้างอินสแตนซ์ใหม่โดยอัตโนมัติ useValue ใช้ค่าคงที่ useExisting สามารถใช้อินสแตนซ์ที่มีอยู่ซ้ำได้ และ useFactory ถูกสร้างขึ้นผ่านฟังก์ชัน โดยมี deps ที่ระบุและพารามิเตอร์ Constructor ที่ระบุสามารถใช้งานได้หลากหลาย คุณสามารถตัดโทเค็นโทเค็นของคลาสออกและแทนที่ด้วยอินสแตนซ์อื่นที่คุณเตรียมไว้ได้ คุณสามารถสร้างโทเค็นเพื่อบันทึกค่าหรืออินสแตนซ์ก่อน จากนั้นจึงแทนที่อีกครั้งเมื่อคุณต้องการใช้ในภายหลัง คุณยังสามารถใช้ได้อีกด้วย ฟังก์ชันโรงงานเพื่อส่งคืนข้อมูลในเครื่องของอินสแตนซ์ถูกแมปกับออบเจ็กต์หรือค่าแอตทริบิวต์อื่น รูปแบบการเล่นที่นี่จะมีการอธิบายในกรณีต่อไปนี้ ดังนั้นฉันจะไม่พูดถึงมันที่นี่ เว็บไซต์อย่างเป็นทางการยังมีตัวอย่างมากมายสำหรับการอ้างอิง
การฉีดใน Angular สามารถฉีดภายใน Constructor หรือคุณสามารถรับ injector เพื่อรับองค์ประกอบที่ฉีดที่มีอยู่ผ่านเมธอด get
Angular รองรับการเพิ่มมัณฑนากรเพื่อทำเครื่องหมายเมื่อทำการฉีด
มีบทความ "@Self หรือ @Optional @Host? The Visual Guide to Angular DI Decorators" ซึ่งแสดงให้เห็นอย่างชัดเจนมากว่าหากมีการใช้มัณฑนากรที่แตกต่างกันระหว่างส่วนประกอบหลักและลูก ตัวอย่างที่จะได้รับผลกระทบในที่สุดคือ: ความแตกต่าง.
รูปที่ 3 การกรองผลลัพธ์ของการตกแต่งที่ฉีดเข้าไปที่แตกต่างกัน
ในบรรดามุมมองโฮสต์และการตกแต่ง @Host นั้น @Host อาจเป็นคำสั่งที่เข้าใจยากที่สุด ต่อไปนี้เป็นคำแนะนำเฉพาะบางส่วนสำหรับ @Host คำอธิบายอย่างเป็นทางการของ @Host มัณฑนากรคือ
...ดึงข้อมูลการพึ่งพาจากหัวฉีดใด ๆ จนกระทั่งถึงองค์ประกอบโฮสต์
โฮสต์ที่นี่หมายถึงโฮสต์ @Host มัณฑนากรจะจำกัดขอบเขตของการสืบค้นภายในองค์ประกอบโฮสต์ องค์ประกอบโฮสต์คืออะไร? หากส่วนประกอบ B เป็นส่วนประกอบที่ใช้โดยเทมเพลตของส่วนประกอบ A อินสแตนซ์ของส่วนประกอบ A ก็คือองค์ประกอบโฮสต์ของอินสแตนซ์ของส่วนประกอบ B เนื้อหาที่สร้างโดยเทมเพลตส่วนประกอบเรียกว่ามุมมองเดียวกันอาจมีมุมมองที่แตกต่างกันสำหรับส่วนประกอบที่แตกต่างกัน หากส่วนประกอบ A ใช้ส่วนประกอบ B ภายในขอบเขตเทมเพลตของตัวเอง (ดูรูปที่ 4) มุมมอง (ส่วนกล่องสีแดง) ที่เกิดจากเนื้อหาเทมเพลตของ A จะเป็นมุมมองแบบฝังของส่วนประกอบ A และส่วนประกอบ B จะอยู่ภายในมุมมองนี้ ดังนั้นสำหรับ B มุมมองนี้เป็นมุมมองโฮสต์ของ B มัณฑนากร @Host จำกัดขอบเขตการค้นหาไว้ที่มุมมองโฮสต์ หากไม่พบ ก็จะไม่เกิดฟอง
รูปที่ 4 มุมมองแบบฝังและมุมมองโฮสต์
ลองใช้เคสจริงเพื่อดูว่า dependency insert ทำงานอย่างไร วิธีแก้ไขข้อผิดพลาด และวิธีการเล่น
หน้าต่างโมดอลของไลบรารีส่วนประกอบ DevUI ให้บริการ ModalService ซึ่งสามารถเปิดกล่องโมดอลและสามารถกำหนดค่าเป็นส่วนประกอบที่กำหนดเองได้ นักศึกษาธุรกิจมักจะรายงานข้อผิดพลาดเมื่อใช้ส่วนประกอบนี้ โดยบอกว่าแพ็คเกจไม่พบส่วนประกอบที่กำหนดเอง
ตัวอย่างเช่น มีรายงานข้อผิดพลาดต่อไปนี้:
รูปที่ 5 เมื่อใช้ ModalService มีข้อผิดพลาดเมื่อสร้างส่วนประกอบที่อ้างอิงถึง EditorX ไม่พบผู้ให้บริการที่เกี่ยวข้อง
วิเคราะห์วิธีที่ ModalService สร้างส่วนประกอบที่กำหนดเองของฟังก์ชัน Open ของซอร์สโค้ด ModalService ดังที่คุณเห็นว่า หากไม่ได้ส่งผ่าน componentFactoryResolver
ระบบจะใช้ componentFactoryResolver
ที่ ModalService ฉีดเข้ามา ในกรณีส่วนใหญ่ ธุรกิจจะแนะนำ DevUIModule หนึ่งครั้งในโมดูลรูท แต่จะไม่แนะนำ ModalModule ในโมดูลปัจจุบัน นั่นคือสถานการณ์ปัจจุบันในรูปที่ 6 จะเป็นเช่นนี้ ตามรูปที่ 6 ไม่มี EditorXModuleService ใน injector ของ ModalService
รูปที่ 6 แผนภาพความสัมพันธ์การให้บริการโมดูล
ตามการสืบทอดของ injector มีวิธีแก้ปัญหาสี่วิธี:
ใส่ EditorXModule โดยที่ ModalModule ถูกประกาศ เพื่อให้ injector สามารถค้นหา EditorModuleService ที่จัดทำโดย EditorXModule - นี่เป็นวิธีแก้ปัญหาที่แย่ที่สุดในตัวมันเอง การโหลดแบบ Lazy Loading ถูกนำมาใช้ โดย loadChildren คือการลดการโหลดของโมดูลโฮมเพจ ผลลัพธ์ก็คือ เนื้อหาที่จำเป็นต้องใช้ในหน้าย่อยจะถูกวางไว้ใน AppModule โมดูล Rich Text ขนาดใหญ่จะถูกโหลดในการโหลดครั้งแรก ซึ่งทำให้รุนแรงขึ้น FMP (First Meaningful Paint) ไม่ควรรับประทาน
แนะนำ ModalService ในโมดูลที่แนะนำ EditorXModule และใช้ ModalService - ขอแนะนำ มีเพียงสถานการณ์เดียวที่ไม่แนะนำให้เลือกนั่นคือการเรียก ModalService เป็นอีกหนึ่งบริการสาธารณะระดับบนสุดซึ่งยังคงวางโมดูลที่ไม่จำเป็นไว้ที่ชั้นบนสำหรับการโหลด
เมื่อทริกเกอร์ส่วนประกอบโดยใช้ ModalService ให้ฉีด componentFactoryResolver
ของโมดูลปัจจุบันและส่งไปยังพารามิเตอร์ฟังก์ชันเปิดของ ModalService ขอแนะนำให้แนะนำ EditorXModule ในที่ที่มีการใช้งานจริง
ในโมดูลที่ใช้ ขอแนะนำให้จัดเตรียม ModalService ด้วยตนเอง ซึ่งจะช่วยแก้ปัญหาการแทรกการค้นหา
วิธีการทั้งสี่กำลังแก้ไขปัญหาของ EditorXModuleService ในห่วงโซ่ภายในของ injector ของ componentFactoryResolver
ที่ใช้โดย ModalService การตรวจสอบให้แน่ใจว่าห่วงโซ่การค้นหาอยู่ที่สองระดับ ปัญหานี้ก็จะสามารถแก้ไขได้
สรุปประเด็นความรู้ : การสืบทอดโมดูลอินเจคเตอร์และขอบเขตการค้นหา
โดยปกติแล้วเมื่อเราใช้เทมเพลตเดียวกันในหลาย ๆ ที่ เราจะแยกส่วนทั่วไปผ่านเทมเพลต เมื่อส่วนประกอบ DevUI Select ได้รับการพัฒนามาก่อน นักพัฒนาต้องการแยกส่วนทั่วไปและรายงาน ข้อผิดพลาด.
รูปที่ 7 ไม่พบข้อผิดพลาดในการเคลื่อนที่และการฉีด
เนื่องจากคำสั่ง CdkVirtualScrollFor จำเป็นต้องฉีด CdkVirtualScrollViewport อย่างไรก็ตาม ระบบสืบทอดหัวฉีดองค์ประกอบจะสืบทอด DOM ของความสัมพันธ์ AST แบบคงที่ และไม่สามารถทำได้ ลักษณะการทำงานของแบบสอบถามต่อไปนี้เกิดขึ้น และการค้นหาล้มเหลว
รูปที่ 8 Element injector Query Chain Search Range
วิธีแก้ปัญหาสุดท้าย: 1) คงตำแหน่งโค้ดต้นฉบับไว้ไม่เปลี่ยนแปลง หรือ 2) คุณต้องฝังเทมเพลตทั้งหมดเพื่อค้นหา
รูปที่ 9 การฝังโมดูลทั้งหมดทำให้ CdkVitualScrollFo ค้นหา CdkVirtualScrollViewport (โซลูชันที่ 2)
สรุปประเด็นความรู้ : สายการสืบค้นขององค์ประกอบ injector คือบรรพบุรุษองค์ประกอบ DOM ของเทมเพลตแบบคงที่
กรณีนี้มาจากบล็อก "เชิงมุม: แบบฟอร์มที่ขับเคลื่อนด้วยเทมเพลตที่ซ้อนกัน"
เรายังพบปัญหาเดียวกันเมื่อใช้การตรวจสอบแบบฟอร์ม ดังที่แสดงในรูปที่ 10 ด้วยเหตุผลบางประการ เราจึงสรุปที่อยู่ของทั้งสามฟิลด์ให้เป็นส่วนประกอบเพื่อนำมาใช้ซ้ำ
รูปที่ 10: สรุปฟิลด์ที่อยู่ทั้งสามของแบบฟอร์มให้เป็นองค์ประกอบย่อย
ในขณะนี้ เราจะพบว่ามีการรายงานข้อผิดพลาด ngModelGroup
ต้องใช้ ControlContainer
ภายในโฮสต์ ซึ่งเป็นเนื้อหาที่จัดทำโดยคำสั่ง ngForm
รูปที่ 11 ngModelGroup ไม่พบ ControlContainer
เมื่อดูโค้ด ngModelGroup คุณจะเห็นว่ามันเพิ่มข้อจำกัดของตัวตกแต่งโฮสต์เท่านั้น
รูปที่ 12 ng_model_group.ts จำกัดขอบเขตของการฉีด ControlContainer
ที่นี่ คุณสามารถใช้ viewProvider พร้อมกับ useExisting เพื่อเพิ่มผู้ให้บริการของ ControlContainer ให้กับมุมมองโฮสต์ของ AddressComponent
รูปที่ 13 การใช้ viewProviders เพื่อจัดเตรียม
จุดความรู้ของผู้ให้บริการภายนอกสำหรับส่วนประกอบที่ซ้อนกัน สรุป คะแนนความรู้: การใช้งานที่ยอดเยี่ยมของ viewProvider และการใช้งานที่มีอยู่
การโหลดแบบ Lazy Loading ส่งผลให้ไม่สามารถลากและวางซึ่งกันและกันได้ แพลตฟอร์มธุรกิจภายในเกี่ยวข้องกับการลากและวางข้ามหลายโมดูลเนื่องจากขี้เกียจ กำลังโหลด loadChildren แต่ละโมดูลจะ DragDropModule ของไลบรารีคอมโพเนนต์ DevUI จะถูกบรรจุแยกกัน และโมดูลนี้จะมี DragDropService คำแนะนำแบบลากและวางแบ่งออกเป็นคำสั่ง Draggable และคำสั่ง Droppable ทั้งสองคำสั่งสื่อสารผ่าน DragDropService เดิมที เป็นไปได้ที่จะสื่อสารโดยการแนะนำโมดูลเดียวกันและใช้บริการที่โมดูลจัดให้ อย่างไรก็ตาม หลังจากการโหลดแบบ Lazy Loading โมดูล DragDropModule จะถูกแพ็กสองครั้ง ซึ่งส่งผลให้มีอินสแตนซ์ที่แยกออกจากกันสองตัวด้วย ในขณะนี้ คำสั่ง Draggable ในโมดูลที่โหลดแบบ Lazy ไม่สามารถสื่อสารกับคำสั่ง Droppable ในโมดูลที่โหลดแบบ Lazy อื่นได้ เนื่องจาก DragDropService ไม่ใช่อินสแตนซ์เดียวกันในขณะนี้
รูปที่ 14 การโหลดโมดูลแบบ Lazy ส่งผลให้บริการไม่เป็นอินสแตนซ์/กรณีเดียว
เห็นได้ชัดว่าข้อกำหนดของเราในที่นี้คือเราต้องการซิงเกิลตัน และโดยปกติแล้ววิธีการของซิงเกิลตันจะเป็น providerIn: 'root'
DragDropService ของไลบรารีส่วนประกอบ เป็นการดีที่จะจัดเตรียมโดเมนรูทโดยตรงที่ระดับโมดูล แต่ถ้าคุณคิดให้รอบคอบแล้วยังมีปัญหาอื่นอยู่อีก ไลบรารีส่วนประกอบนั้นมีไว้เพื่อใช้งานโดยธุรกิจต่างๆ หากธุรกิจบางแห่งมีกลุ่มการลากและวางที่เกี่ยวข้องกันสองกลุ่มในสองตำแหน่งบนเพจ ธุรกิจเหล่านั้นก็ไม่ต้องการเชื่อมโยงกัน ในเวลานี้ ซิงเกิลตันจะทำลายการแยกตามธรรมชาติตามโมดูล
จากนั้นจะเหมาะสมกว่าที่จะใช้การแทนที่ซิงเกิลตันโดยฝ่ายธุรกิจ จำสายการสืบค้นการพึ่งพาที่เรากล่าวถึงก่อนหน้านี้ หากไม่พบ โมดูลหัวฉีดจะเริ่มทำงาน ดังนั้นแนวคิดในการทดแทนก็คือเราสามารถจัดหาผู้ให้บริการระดับองค์ประกอบได้
รูปที่ 15 ใช้วิธีการขยายเพื่อรับ DragDropService ใหม่และทำเครื่องหมายว่าให้ไว้ที่ระดับรูท
รูปที่ 16 คุณสามารถใช้ตัวเลือกเดียวกันเพื่อซ้อนคำสั่งที่ซ้ำกัน วางคำสั่งเพิ่มเติมในคำสั่ง Draggable และคำสั่ง Droppable ของไลบรารีส่วนประกอบ และแทนที่โทเค็นของ DragDropService ด้วย DragDropGlobalService ที่ให้ซิงเกิลตันที่รูท
ดังที่แสดงใน รูปที่ 15 และ 16 เราแทรกผ่านองค์ประกอบต่างๆ ตัวจัดการจะซ้อนคำสั่งและแทนที่โทเค็น DragDropService ด้วยอินสแตนซ์ของซิงเกิลตันระดับโลกของเราเอง ในเวลานี้ เมื่อเราจำเป็นต้องใช้ DragDropService ซิงเกิลตันระดับโลก เราเพียงแต่แนะนำโมดูลที่ประกาศและส่งออกคำสั่งพิเศษทั้งสองนี้เพื่อเปิดใช้งานคำสั่ง Draggable คำแนะนำ Droppable ของไลบรารีส่วนประกอบเพื่อสื่อสารข้ามโมดูลที่โหลดแบบ Lazy
สรุปประเด็นความรู้ : องค์ประกอบหัวฉีดมีลำดับความสำคัญสูงกว่าโมดูลหัวฉีด
ของไลบรารีส่วนประกอบ DevUI ใช้แอตทริบิวต์ที่กำหนดเอง CSS (ตัวแปร css) เพื่อประกาศค่าตัวแปร css ของรูทเพื่อให้สามารถสลับธีมได้ . หากเราต้องการแสดงตัวอย่างธีมต่างๆ ในเวลาเดียวกันในอินเทอร์เฟซเดียว เราสามารถประกาศตัวแปร css อีกครั้งภายในองค์ประกอบ DOM เพื่อให้บรรลุการทำงานของธีมท้องถิ่น เมื่อตอนที่ฉันสร้างตัวสร้างธีมแบบไดเทอร์มาก่อน ฉันใช้วิธีนี้เพื่อนำธีมไปใช้ในเครื่อง
รูปที่ 17 ฟังก์ชั่นธีมท้องถิ่น
แต่ไม่เพียงพอที่จะใช้ค่าตัวแปร CSS ในเครื่อง มีเลเยอร์ป๊อปอัปแบบเลื่อนลงบางเลเยอร์ที่แนบไว้ที่ด้านหลังของร่างกายตามค่าเริ่มต้น ซึ่งหมายความว่าเลเยอร์ไฟล์แนบอยู่ด้านนอก ตัวแปรท้องถิ่นซึ่งจะนำไปสู่ปัญหาที่น่าอับอายมาก กล่องแบบเลื่อนลงของส่วนประกอบธีมท้องถิ่นจะแสดงสไตล์ของธีมภายนอก
รูปที่ 18 ส่วนประกอบในธีมภายในเครื่องแนบมากับกล่องดรอปดาวน์โอเวอร์เลย์ภายนอก
ฉันควรทำอย่างไรหากธีมไม่ถูกต้อง เราควรย้ายจุดแนบกลับเข้าไปในโดมธีมท้องถิ่น
เป็นที่ทราบกันดีว่าการซ้อนทับของส่วนประกอบ DatePickerPro ของไลบรารีส่วนประกอบ Devui ใช้การซ้อนทับของ CDK
เชิงมุม ด้านล่าง.
รูปที่ 19 ปรับแต่ง ElementOverlayContainer และแทนที่ตรรกะ _createContainer
2) จากนั้นจัดเตรียม ElementOverlayContainer ใหม่ของเราโดยตรงที่ฝั่งส่วนประกอบของการแสดงตัวอย่าง และจัดเตรียม Overlay ใหม่เพื่อให้ Overlay ใหม่สามารถใช้ OverlayContainer ของเราได้ เดิมที Overlay และ OverlayContainer มีให้บนรูท ที่นี่เราต้องครอบคลุมทั้งสองสิ่งนี้
รูปที่ 20 แทนที่ OverlayContainer ด้วย ElementOverlayContainer ที่กำหนดเองและให้การซ้อนทับ
ใหม่
รูปที่
21 คอนเทนเนอร์ซ้อนทับของ CDK ถูกแนบมากับ DOM ที่ระบุ
สุดท้ายนี้ เลเยอร์ป๊อปอัปและเลเยอร์ป๊อปอัปอื่นๆ สามารถรับรู้ได้เพื่อรองรับธีมท้องถิ่นได้อย่างสมบูรณ์แบบ
สรุปประเด็นความรู้ : รูปแบบนามธรรมที่ดีสามารถทำให้โมดูลสามารถเปลี่ยนได้และบรรลุการเขียนโปรแกรมด้านที่สวยงามได้
กับกรณีสุดท้าย ฉันต้องการพูดคุยเกี่ยวกับแนวทางที่เป็นทางการน้อยลง ช่วยให้ทุกคนเข้าใจธรรมชาติของผู้ให้บริการได้ โดยพื้นฐานแล้วการกำหนดค่าผู้ให้บริการหมายถึงการปล่อยให้ผู้ให้บริการช่วยคุณสร้างอินสแตนซ์หรือแมปกับอินสแตนซ์ที่มีอยู่
เรารู้ว่าหากใช้ cdkOverlay ถ้าเราต้องการให้กล่องป๊อปอัปตามแถบเลื่อนและหยุดอยู่ในตำแหน่งที่ถูกต้อง เราจำเป็นต้องเพิ่มคำสั่ง cdkScrollable ให้กับแถบเลื่อน
ยังคงเป็นสถานการณ์เดียวกันกับตัวอย่างก่อนหน้านี้ หน้าทั้งหมดของเราโหลดผ่านการกำหนดเส้นทาง เพื่อความง่าย ฉันจึงเขียนแถบเลื่อนบนโฮสต์ของส่วนประกอบ
รูปที่ 22 แถบเลื่อนเนื้อหาล้นเขียนโอเวอร์โฟลว์:อัตโนมัติในส่วนประกอบ:โฮสต์
วิธีนี้ทำให้เราพบปัญหาที่ยากขึ้น โมดูลถูกระบุโดยคำจำกัดความของเราเตอร์ นั่นคือ <app-theme-picker-customize></app-theme-picker-customize>
แล้วจะเพิ่มคำสั่ง cdkScrollable ได้อย่างไร? วิธีแก้ไขมีดังนี้ โค้ดบางส่วนถูกซ่อนอยู่ที่นี่และเหลือเพียงโค้ดหลักเท่านั้น
รูปที่ 23 สร้างอินสแตนซ์ผ่านการฉีดและเรียกใช้วงจรการใช้งานด้วยตนเอง
ในที่นี้ อินสแตนซ์ของ cdkScrollable จะถูกสร้างขึ้นผ่านการฉีด และวงจรการใช้งานจะถูกเรียกพร้อมกันในระหว่างขั้นตอนวงจรชีวิตของส่วนประกอบ
วิธีแก้ปัญหานี้ไม่ใช่วิธีการที่เป็นทางการ แต่ช่วยแก้ปัญหาได้ ทิ้งไว้ที่นี่เพื่อเป็นแนวคิดและการสำรวจให้ผู้อ่านได้ลิ้มลอง
สรุปประเด็นความรู้ : ผู้ให้บริการกำหนดค่าการขึ้นต่อกันของการฉีดสามารถสร้างอินสแตนซ์ได้ แต่โปรดทราบว่าอินสแตนซ์จะถือเป็นคลาสบริการทั่วไปและไม่สามารถมีวงจรชีวิตที่สมบูรณ์ได้
โปรดดูโพสต์ในบล็อกนี้: "การแสดงผลแอปพลิเคชัน Angular ใน Terminal"
รูปที่ 24 แทนที่ตัวเรนเดอร์ RendererFactory2 และเนื้อหาอื่นๆ เพื่อให้ Angular สามารถทำงานบนเทอร์มินัล
ได้ ผู้เขียนได้แทนที่ RendererFactory2 และตัวเรนเดอร์อื่นๆ เพื่อให้แอปพลิเคชัน Angular สามารถทำงานบนเทอร์มินัลได้ นี่คือความยืดหยุ่นของการออกแบบเชิงมุม แม้แต่แพลตฟอร์มก็สามารถเปลี่ยนได้ รายละเอียดการเปลี่ยนทดแทนโดยละเอียดสามารถพบได้ในบทความต้นฉบับ และจะไม่ขยายความในที่นี้
สรุปประเด็นความรู้ : พลังของการฉีดการพึ่งพาคือผู้ให้บริการสามารถกำหนดค่าได้ด้วยตัวเอง และสุดท้ายก็นำตรรกะการแทนที่ไปใช้
บทความนี้แนะนำโหมดการฉีดพึ่งพาของการผกผันการควบคุมและประโยชน์ของมัน กรณีวิเคราะห์วิธีการรวมจุดความรู้ของการฉีดขึ้นต่อกันเพื่อแก้ไขปัญหาที่พบในการพัฒนาและการเขียนโปรแกรม
ด้วยการทำความเข้าใจกระบวนการค้นหาการพึ่งพาอย่างถูกต้อง เราสามารถกำหนดค่าผู้ให้บริการในตำแหน่งที่แน่นอน (กรณีที่ 1 และ 2) แทนที่อินสแตนซ์อื่นๆ ด้วยซิงเกิลตัน (กรณีที่ 4 และ 5) และแม้แต่เชื่อมต่อข้ามข้อจำกัดของแพ็คเกจส่วนประกอบที่ซ้อนกัน กรณีที่ 3) หรือใช้เส้นโค้งวิธีการที่ให้ไว้เพื่อใช้การสร้างอินสแตนซ์คำสั่ง (กรณีที่ 6)
กรณีที่ 5 ดูเหมือนจะเป็นสิ่งทดแทนอย่างง่าย แต่การที่สามารถเขียนโครงสร้างรหัสที่สามารถแทนที่ได้ต้องมีความเข้าใจในเชิงลึกเกี่ยวกับโหมดการฉีดและสิ่งที่เป็นนามธรรมที่ดีขึ้นและสมเหตุสมผลของแต่ละฟังก์ชั่น ไม่สามารถใช้ได้ผลสูงสุดจากการฉีด โหมดการฉีดให้พื้นที่ที่เป็นไปได้มากขึ้นสำหรับโมดูลที่สามารถเสียบปลั๊ก เสียบปลั๊ก และยึดตามชิ้นส่วน ลดการมีเพศสัมพันธ์และเพิ่มความยืดหยุ่น เพื่อให้โมดูลสามารถทำงานร่วมกันได้อย่างสวยงามและกลมกลืนกันมากขึ้น
ฟังก์ชันการขึ้นต่อกันที่มีประสิทธิภาพไม่เพียงแต่สามารถปรับเส้นทางการสื่อสารของส่วนประกอบให้เหมาะสมเท่านั้น แต่ที่สำคัญกว่านั้น ยังสามารถบรรลุการควบคุมผกผัน เผยให้เห็นส่วนประกอบที่ห่อหุ้มในแง่มุมต่างๆ ของการเขียนโปรแกรมมากขึ้น และการนำตรรกะเฉพาะทางธุรกิจไปใช้ยังสามารถมีความยืดหยุ่นมากขึ้นอีกด้วย