
วิธีเริ่มต้นใช้งาน VUE3.0 อย่างรวดเร็ว: เข้าสู่และเรียนรู้
Nest จัดเตรียมกลไกการพึ่งพา เสร็จสิ้นโดยการกำหนดผู้ให้บริการ การนำเข้า การส่งออก และตัวสร้างผู้ให้บริการในตัวตกแต่งโมดูล และการพัฒนาแอปพลิเคชันทั้งหมดจะถูกจัดระเบียบผ่าน ต้นไม้โมดูล ไม่มีปัญหาในการเปิดแอปพลิเคชันโดยตรงตามแบบแผนของเฟรมเวิร์กเอง อย่างไรก็ตาม สำหรับฉัน ฉันรู้สึกว่าฉันขาดความเข้าใจที่ชัดเจนและเป็นระบบเกี่ยวกับการขึ้นต่อกัน การผกผันของการควบคุม โมดูล ผู้ให้บริการ เมทาดาทา ผู้ตกแต่งที่เกี่ยวข้อง ฯลฯ ที่ประกาศโดยกรอบงาน
- เหตุใดจึงต้องมีการผกผันการควบคุม?
- การฉีดพึ่งพาคืออะไร?
- มัณฑนากรทำอะไร?
- หลักการดำเนินการของผู้ให้บริการ การนำเข้า และการส่งออกในโมดูล (@Module) คืออะไร
เหมือนจะเข้าใจและซาบซึ้งได้แต่ขออธิบายให้ชัดเจนตั้งแต่ต้นก็อธิบายให้ชัดเจนไม่ได้ ดังนั้นฉันจึงค้นคว้าและเกิดบทความนี้ขึ้นมา จากนี้ไป เราจะเริ่มต้นใหม่ทั้งหมดและป้อนข้อความหลัก
1.1 Express, Koa
กระบวนการพัฒนาของภาษาและชุมชนทางเทคนิคของมันจะต้องค่อยๆ เพิ่มคุณค่าและพัฒนาจากฟังก์ชั่นด้านล่างขึ้นไป เช่นเดียวกับกระบวนการที่รากของต้นไม้ค่อยๆ เติบโตเป็นกิ่งก้านและเต็มไปด้วยใบไม้ ก่อนหน้านี้ กรอบงานบริการเว็บขั้นพื้นฐาน เช่น Express และ Koa ปรากฏใน Nodejs สามารถให้บริการความสามารถขั้นพื้นฐานได้ จากกรอบงานดังกล่าว มิดเดิลแวร์และปลั๊กอินจำนวนมากเริ่มถือกำเนิดขึ้นในชุมชน โดยให้บริการที่สมบูรณ์ยิ่งขึ้นสำหรับกรอบงาน เราจำเป็นต้องจัดระเบียบการพึ่งพาแอปพลิเคชัน และสร้างแอปพลิเคชันสนับสนุนด้วยตัวเราเอง ซึ่งมีความยืดหยุ่นและยุ่งยาก และยังต้องมีภาระงานบางอย่างด้วย
ต่อมาในการพัฒนา กรอบการทำงานบางอย่างที่มีประสิทธิภาพมากขึ้นและกฎที่เป็นหนึ่งเดียวกันมากขึ้นได้ถือกำเนิดขึ้น และนำไปสู่ขั้นตอนที่ใหม่กว่า
1.2 EggJs และ Nestjs
เพื่อให้สามารถปรับตัวเข้ากับแอปพลิเคชันการผลิตที่รวดเร็วยิ่งขึ้น ให้รวมมาตรฐานเข้าด้วยกันและทำให้พร้อมใช้งานทันที เฟรมเวิร์กเช่น EggJs, NestJs และ Midway ได้รับการพัฒนา เฟรมเวิร์กประเภทนี้สรุปการใช้งานแอปพลิเคชันให้เป็นกระบวนการสากลและขยายได้โดยการนำวงจรชีวิตพื้นฐานไปใช้ เราเพียงแต่ต้องปฏิบัติตามวิธีการกำหนดค่าที่กำหนดโดยเฟรมเวิร์กเพื่อใช้งานแอปพลิเคชันได้ง่ายขึ้น เฟรมเวิร์กใช้การควบคุมกระบวนการของโปรแกรม และเราเพียงแค่ประกอบชิ้นส่วนของเราในตำแหน่งที่เหมาะสมเท่านั้น ซึ่งดูเหมือนงานสายการประกอบมากกว่า แต่ละกระบวนการจะถูกแบ่งอย่างชัดเจน และประหยัดค่าใช้จ่ายในการดำเนินการได้มาก
1.3 สรุป
สองขั้นตอนข้างต้นเป็นเพียงการคาดเดา เราสามารถเข้าใจคร่าวๆ ว่าการอัพเกรดเฟรมเวิร์กช่วยปรับปรุงประสิทธิภาพการผลิต เพื่อให้บรรลุการอัพเกรดเฟรมเวิร์ก แนวคิดและรูปแบบการออกแบบบางอย่างจะถูกนำมาใช้ใน Nest dependency insert และแนวคิดของการเขียนโปรแกรมเมตา เรามาพูดถึงกันด้านล่างนี้
2.1 การฉีดการพึ่งพา
จริงๆ แล้วแอปพลิเคชันนั้นเป็นคลาสนามธรรมจำนวนมาก ซึ่งรับรู้ถึงฟังก์ชันทั้งหมดของแอปพลิเคชันโดยการเรียกกันและกัน เมื่อความซับซ้อนของโค้ดแอปพลิเคชันและฟังก์ชันเพิ่มขึ้น โปรเจ็กต์ก็จะยากขึ้นเรื่อยๆ อย่างแน่นอนในการบำรุงรักษา เนื่องจากมีคลาสเพิ่มมากขึ้นเรื่อยๆ และความสัมพันธ์ระหว่างคลาสเหล่านั้นก็ซับซ้อนมากขึ้นเรื่อยๆ
ตัวอย่างเช่น หากเราใช้ Koa เพื่อพัฒนาแอปพลิเคชันของเรา Koa เองก็ใช้ชุดความสามารถพื้นฐานของบริการเว็บเป็นหลัก ในกระบวนการใช้งานแอปพลิเคชัน เราจะกำหนดคลาสต่างๆ วิธีการสร้างอินสแตนซ์ และการพึ่งพาซึ่งกันและกันของคลาสเหล่านี้ ทั้งหมดจะ ได้รับการจัดระเบียบและควบคุมโดยเราอย่างอิสระในตรรกะของโค้ด การสร้างอินสแตนซ์ของแต่ละคลาสนั้นเราสร้างขึ้นใหม่ด้วยตนเอง และเราสามารถควบคุมได้ว่าจะให้คลาสสร้างอินสแตนซ์เพียงครั้งเดียวแล้วแชร์ หรือไม่ว่าจะสร้างอินสแตนซ์ทุกครั้งหรือไม่ คลาส B ต่อไปนี้ขึ้นอยู่กับ A ทุกครั้งที่สร้างอินสแตนซ์ B แล้ว A จะถูกสร้างอินสแตนซ์หนึ่งครั้ง ดังนั้นสำหรับแต่ละอินสแตนซ์ B A จึงเป็นอินสแตนซ์ที่ไม่ได้แชร์
คลาส เอ{}
// บี
คลาส B{
ตัวสร้าง () {
this.a = ใหม่ A();
-
} C ด้านล่างเป็นอินสแตนซ์ภายนอกที่ได้รับ ดังนั้นอินสแตนซ์ C หลายรายการจึงแชร์อินสแตนซ์ app.a
คลาส เอ{}
// ซี
แอป const = {};
app.a = ใหม่ A();
คลาส C{
ตัวสร้าง () {
นี้.a = app.a;
-
} D ต่อไปนี้ถูกส่งผ่านพารามิเตอร์ Constructor คุณสามารถส่งผ่านในอินสแตนซ์ที่ไม่ได้แชร์ในแต่ละครั้ง หรือคุณสามารถส่งผ่านในอินสแตนซ์ app.a ที่แชร์ (D และ F แชร์ app.a) และด้วยเหตุนี้ ตอนนี้เป็นพารามิเตอร์ Pass in ฉันสามารถส่งผ่านอินสแตนซ์คลาส X ได้เช่นกัน
คลาส เอ{}
คลาส X{}
//ด
แอป const = {};
app.a = ใหม่ A();
คลาส D{
ตัวสร้าง (ก) {
นี่.a = ก;
-
-
คลาส F{
ตัวสร้าง (ก) {
นี่.a = ก;
-
-
ใหม่ D(app.a)
ใหม่ F(app.a)
ใหม่
D(ใหม่
การฉีดผ่าน Constructor (การส่งผ่านค่า) เป็นเพียงวิธีการใช้งานวิธีเดียวเท่านั้น นอกจากนี้ยังสามารถส่งผ่านได้โดยการใช้การเรียกเมธอด set หรือวิธีอื่นใด ตราบใดที่การพึ่งพาภายนอกสามารถส่งผ่านไปยังวิธีภายในได้ มันง่ายมากจริงๆ
คลาส เอ{}
//ด
คลาส D{
setDep(ก){
นี่.a = ก;
-
-
const d = D ใหม่()
d.setDep(new A()) 2.2 ทั้งหมดอยู่ในการฉีดพึ่งพาหรือไม่
เมื่อการวนซ้ำดำเนินไป ปรากฏว่าการขึ้นต่อกันของ B จะเปลี่ยนไปตามเงื่อนไขเบื้องต้นที่แตกต่างกัน ตัวอย่างเช่น กำหนดเงื่อนไขล่วงหน้าหนึ่ง this.a จะต้องผ่านในอินสแตนซ์ของ A และกำหนดเงื่อนไขล่วงหน้าสองรายการ this.a จะต้องผ่านในอินสแตนซ์ของ X ในเวลานี้เราจะเริ่มทำสิ่งที่เป็นนามธรรมจริง เราจะเปลี่ยนมันเป็นวิธีการฉีดแบบพึ่งพาเช่น D ข้างต้น
ในช่วงแรกๆ เมื่อเรานำแอปพลิเคชันไปใช้ เราจะใช้วิธีการเขียนของคลาส B และ C ตราบใดที่มันตรงตามความต้องการในขณะนั้น ซึ่งนั่นไม่ใช่ปัญหาเลย หลังจากที่โปรเจ็กต์ทำซ้ำมาหลายปีแล้ว ของรหัสไม่จำเป็นต้องถูกแตะต้อง หากพิจารณาขยายในภายหลังจะส่งผลต่อประสิทธิภาพการพัฒนาและอาจไม่เกิดประโยชน์ โดยส่วนใหญ่แล้ว เราพบสถานการณ์ที่ต้องใช้นามธรรม จากนั้นจึงแปลงส่วนหนึ่งของโค้ดในทางนามธรรม
// คลาส B{ ก่อนการแปลง
ตัวสร้าง () {
this.a = ใหม่ A();
-
-
ใหม่บี()
//คลาส D{ หลังการเปลี่ยนแปลง
ตัวสร้าง (ก) {
นี่.a = ก;
-
-
ใหม่ D(ใหม่ A())
ใหม่ D ( ค่าใช้จ่ายในการดำเนินการ
ใหม่
ตัวอย่างนี้ให้ไว้ที่นี่เพื่อแสดงให้เห็นว่าในรูปแบบการพัฒนาโดยไม่มีข้อจำกัดหรือข้อบังคับใดๆ เราสามารถเขียนโค้ดได้อย่างอิสระเพื่อควบคุมการพึ่งพาระหว่างคลาสต่างๆ ในสภาพแวดล้อมที่เปิดกว้างอย่างสมบูรณ์ นี่เป็นยุคดั้งเดิมของการทำฟาร์มแบบเฉือนแล้วเผา เนื่องจากไม่มีรูปแบบการพัฒนาโค้ดแบบตายตัวและไม่มีแผนปฏิบัติการสูงสุด เนื่องจากนักพัฒนาที่แตกต่างกันเข้ามาแทรกแซงหรือนักพัฒนาคนเดียวกันเขียนโค้ดในเวลาที่ต่างกัน ความสัมพันธ์ในการพึ่งพาจะแตกต่างกันอย่างมากเมื่อโค้ดเติบโตขึ้น เห็นได้ชัดว่าอินสแตนซ์ที่ใช้ร่วมกันอาจถูกสร้างอินสแตนซ์หลายครั้ง , เสียความทรงจำ จากโค้ด เป็นการยากที่จะเห็นโครงสร้างการพึ่งพาที่สมบูรณ์ และโค้ดอาจกลายเป็นเรื่องยากมากที่จะรักษา

จากนั้นทุกครั้งที่เรากำหนดคลาส เราจะเขียนมันตามวิธีการ dependency insert และเขียนมันเหมือนกับ D จากนั้นกระบวนการนามธรรมของ C และ B จะเป็นขั้นสูง ซึ่งทำให้การขยายในภายหลังสะดวกยิ่งขึ้น และลดต้นทุนของการเปลี่ยนแปลง ดังนั้นสิ่งนี้จึงเรียกว่า All in 依赖注入นั่นคือการพึ่งพาทั้งหมดของเราถูกนำไปใช้ผ่าน dependency injection
อย่างไรก็ตาม ค่าใช้จ่ายในการดำเนินการในช่วงแรกกลับมาสูงอีกครั้ง และเป็นการยากที่จะบรรลุความสามัคคีและความคงอยู่ของการทำงานร่วมกันเป็นทีม ในท้ายที่สุด การดำเนินการนี้อาจล้มเหลวได้เนื่องจากการออกแบบที่มากเกินไป เนื่องจากต้นทุนการดำเนินการเพิ่มเติมอาจไม่ จำเป็นต้องบรรลุผลสำเร็จ
2.3 การผกผันของการควบคุม
ตอนนี้เราได้ตกลงเกี่ยวกับการใช้การพึ่งพาแบบรวมศูนย์แล้ว เราสามารถใช้คอนโทรลเลอร์ระดับล่างสุดผ่านการห่อหุ้มพื้นฐานของเฟรมเวิร์กและตกลงในกฎการกำหนดค่าการพึ่งพาได้หรือไม่ คอนโทรลเลอร์จะควบคุมกระบวนการสร้างอินสแตนซ์ตาม การกำหนดค่าการพึ่งพาที่เรากำหนดไว้ และการแบ่งปันการพึ่งพาเพื่อช่วยให้เราบรรลุการจัดการชั้นเรียน รูปแบบการออกแบบนี้เรียกว่า การผกผันของการควบคุม
การผกผันของการควบคุมอาจเป็นเรื่องยากที่จะเข้าใจเมื่อคุณได้ยินมันเป็นครั้งแรก การควบคุมหมายถึงอะไร? สิ่งที่ถูกย้อนกลับ?
สันนิษฐานว่าเป็นเพราะนักพัฒนาได้ใช้เฟรมเวิร์กดังกล่าวตั้งแต่เริ่มต้นและไม่เคยสัมผัสกับ "ยุค Express และ Koa" ที่ผ่านมาและขาดการทุบตีของสังคมเก่า ประกอบกับการใช้คำกลับกัน ทำให้โปรแกรมดูเป็นนามธรรมและเข้าใจยาก
ดังที่เราได้กล่าวไว้ข้างต้น เมื่อใช้งานแอปพลิเคชัน Koa คลาสทั้งหมดจะถูกควบคุมโดยเราอย่างสมบูรณ์ ดังนั้นจึงถือได้ว่าเป็นวิธีการควบคุมโปรแกรมทั่วไป ดังนั้นเราจึงเรียกมันว่า: ควบคุมการหมุนไปข้างหน้า เราใช้ Nest ซึ่งใช้ชุดตัวควบคุมที่ด้านล่าง เราเพียงแต่ต้องเขียนโค้ดการกำหนดค่าตามข้อตกลงในระหว่างกระบวนการพัฒนาจริง และโปรแกรมเฟรมเวิร์กจะช่วยเราจัดการการพึ่งพาการฉีดคลาส ดังนั้นเราจึงเรียกมันว่า: การผกผันของการควบคุม
สาระสำคัญคือการมอบกระบวนการใช้งานโปรแกรมให้กับโปรแกรมเฟรมเวิร์กสำหรับการจัดการแบบรวมศูนย์ และถ่ายโอนอำนาจการควบคุมจากนักพัฒนาไปยังโปรแกรมเฟรมเวิร์ก
ควบคุมการหมุนไปข้างหน้า: โปรแกรมควบคุมด้วยตนเองของนักพัฒนาเท่านั้น
การผกผันของการควบคุม: การควบคุมโปรแกรมกรอบงาน
เพื่อเป็นตัวอย่างที่แท้จริง บุคคลหนึ่งขับรถไปทำงานด้วยตัวเอง และจุดประสงค์ของเขาคือไปถึงบริษัท มันขับเคลื่อนตัวเองและควบคุมเส้นทางของตัวเอง และถ้าเขามอบการควบคุมการขับรถและขึ้นรถบัส เขาเพียงแค่ต้องเลือกรถบัสรับส่งที่เกี่ยวข้องเพื่อไปยังบริษัทเท่านั้น ในแง่ของการควบคุมเพียงอย่างเดียว ผู้คนก็ได้รับการปลดปล่อย พวกเขาเพียงต้องจำไว้ว่าจะต้องขึ้นรถบัสคันไหน โอกาสที่จะทำผิดพลาดก็ลดลงเช่นกัน และผู้คนก็ผ่อนคลายมากขึ้น ระบบบัสคือตัวควบคุม และสายบัสคือการกำหนดค่าที่ตกลงกันไว้
จากการเปรียบเทียบจริงข้างต้น ฉันคิดว่าฉันควรจะเข้าใจการผกผันของการควบคุมได้
2.4 สรุป
จาก Koa ถึง Nest จาก front-end JQuery ไปจนถึง Vue React ในความเป็นจริง สิ่งเหล่านี้ล้วนถูกนำไปใช้ทีละขั้นตอนผ่านการห่อหุ้มกรอบการทำงานเพื่อแก้ไขปัญหาความไร้ประสิทธิภาพในยุคก่อน
การพัฒนาแอปพลิเคชัน Koa ข้างต้นใช้วิธีการดั้งเดิมในการควบคุมการพึ่งพาและการสร้างอินสแตนซ์ ซึ่งคล้ายกับปฏิบัติการ JQuery ในส่วนหน้า วิธีดั้งเดิมนี้เรียกว่าการส่งต่อการควบคุม และ Vue React ก็เหมือนกับที่ Nest จัดเตรียมไว้ ตัวควบคุม ทั้งหมดนี้เรียกได้ว่าเป็นการผกผันของการควบคุม นี่เป็นความเข้าใจส่วนตัวของฉันด้วย หากมีปัญหาใดๆ ฉันหวังว่าพระเจ้าจะทรงชี้ให้เห็น
เรามาพูดถึงโมดูล @Module ใน Nest กันเถอะ
Nestjs ใช้การกลับกันของการควบคุมและตกลงที่จะกำหนดค่าการนำเข้า การส่งออก และผู้ให้บริการของโมดูล (@module) เพื่อจัดการผู้ให้บริการ ซึ่งเป็นการฉีดการพึ่งพาของคลาส
ผู้ให้บริการสามารถเข้าใจได้ว่ากำลังลงทะเบียนและสร้างอินสแตนซ์คลาสในโมดูลปัจจุบัน A และ B ต่อไปนี้จะถูกสร้างอินสแตนซ์ในโมดูลปัจจุบัน หาก B อ้างอิงถึง A ในตัวสร้างอินสแตนซ์นั้นจะอ้างถึงอินสแตนซ์ A ของ ModuleD ปัจจุบัน
นำเข้า { โมดูล } จาก '@nestjs/common';
นำเข้า { ModuleX } จาก './moduleX';
นำเข้า { A } จาก './A';
นำเข้า { B } จาก './B';
@โมดูล({
การนำเข้า: [ModuleX],
ผู้ให้บริการ: [A,B],
การส่งออก: [A]
-
ส่งออกคลาส ModuleD {}
// บี
คลาส B{
ตัวสร้าง (a:A){
นี่.a = ก;
-
} exports หมายถึงคลาสที่สร้างอินสแตนซ์ใน providers ในโมดูลปัจจุบันเป็นคลาสที่สามารถแชร์โดยโมดูลภายนอก ตัวอย่างเช่น เมื่อคลาส C ของ ModuleF ถูกสร้างอินสแตนซ์ ฉันต้องการฉีดอินสแตนซ์คลาส A ของ ModuleD โดยตรง เพียงตั้งค่าการส่งออก A ใน ModuleD และนำเข้า ModuleD ผ่าน imports ใน ModuleF
ตามวิธีการเขียนต่อไปนี้ การผกผันของโปรแกรมควบคุมจะสแกนการขึ้นต่อกันโดยอัตโนมัติ ขั้นแรก ให้ตรวจสอบว่ามีผู้ให้บริการ A ในผู้ให้บริการโมดูลของคุณเองหรือไม่ หากไม่มี ให้มองหาอินสแตนซ์ของ A ใน ModuleD ที่นำเข้ามา พบ รับ A ของ ModuleD อินสแตนซ์ถูกฉีดเข้าไปในอินสแตนซ์ C
นำเข้า { โมดูล } จาก '@nestjs/common';
นำเข้า { ModuleD} จาก './moduleD';
นำเข้า { C } จาก './C';
@โมดูล({
การนำเข้า: [ModuleD],
ผู้ให้บริการ: [C]
-
ส่งออกคลาส ModuleF {}
// ซี
คลาส C {
ตัวสร้าง (a:A){
นี่.a = ก;
-
} ดังนั้น หากคุณต้องการให้โมดูลภายนอกใช้คลาสอินสแตนซ์ของโมดูลปัจจุบัน คุณต้องกำหนดคลาสอินสแตนซ์ใน providers ของโมดูลปัจจุบันก่อน จากนั้นกำหนดและส่งออกคลาสนี้ มิฉะนั้นข้อผิดพลาดจะถูกรายงาน
//แก้ไข @Module({
ผู้ให้บริการ: [A]
ส่งออก: [A]
-
// ข้อผิดพลาด @Module({
ผู้ให้บริการ: [],
การส่งออก: [A]
}) เมื่อมองย้อนกลับไปที่กระบวนการค้นหาอินสแตนซ์ของโมดูลเสริมในภายหลัง
ยังไม่ชัดเจนนัก ประเด็นหลักคือคลาสในผู้ให้บริการจะถูกสร้างอินสแตนซ์ และหลังจากการสร้างอินสแตนซ์แล้ว คลาสเหล่านั้นจะกลายเป็นผู้ให้บริการ เฉพาะคลาสในผู้ให้บริการในโมดูลเท่านั้นที่จะถูกสร้างอินสแตนซ์ และการส่งออกและนำเข้าเป็นเพียงการกำหนดค่าความสัมพันธ์ขององค์กร โมดูลจะให้ความสำคัญกับการใช้ผู้ให้บริการของตัวเอง ถ้าไม่ ให้ตรวจสอบว่าโมดูลที่นำเข้ามีผู้ให้บริการที่เกี่ยวข้องหรือ
ไม่ ให้ฉันพูดถึงบางจุดความรู้
การส่งออก C {
ตัวสร้าง (ส่วนตัว a: A) {
-
} เนื่องจาก TypeScript รองรับพารามิเตอร์ตัวสร้าง (ส่วนตัว, ป้องกัน, สาธารณะ, อ่านอย่างเดียว) เพื่อกำหนดโดยปริยายและโดยอัตโนมัติเป็นแอตทริบิวต์คลาส (คุณสมบัติพารามิเตอร์) จึงไม่จำเป็นต้องใช้ this.a = a นี่คือวิธีที่เขียนใน Nest
แนวคิดของการเขียนโปรแกรมเมตาสะท้อนให้เห็นในกรอบงาน Nest การผกผันของการควบคุมและการตกแต่งคือการนำการเขียนโปรแกรมเมตาไปใช้ สามารถเข้าใจได้โดยคร่าวว่าสาระสำคัญของการเขียนโปรแกรมเมตายังคงเป็นการเขียนโปรแกรม แต่ก็มีโปรแกรมนามธรรมอยู่ตรงกลาง โปรแกรมนามธรรมนี้สามารถระบุข้อมูลเมตา (เช่นข้อมูลอ็อบเจ็กต์ใน @Module) ซึ่งจริงๆ แล้วเป็นความสามารถในการขยายที่สามารถใช้อย่างอื่นได้ โปรแกรมเป็นข้อมูลในการจัดการ เมื่อเราเขียนโปรแกรมเชิงนามธรรม เรากำลังเขียนโปรแกรมเมตา
4.1
ข้อมูลเมตามักถูกกล่าวถึงในเอกสาร Nest แนวคิดของข้อมูลเมตาอาจทำให้เกิดความสับสนเมื่อคุณเห็นข้อมูลดังกล่าวเป็นครั้งแรก คุณต้องทำความคุ้นเคยและทำความเข้าใจเมื่อเวลาผ่านไป ดังนั้นคุณจึงไม่จำเป็นต้องทำความเข้าใจเช่นกัน พันกัน
คำจำกัดความของเมทาดาทาคือ ข้อมูลที่อธิบายข้อมูล ซึ่งส่วนใหญ่เป็นข้อมูลที่อธิบายคุณลักษณะของข้อมูล และยังอาจเข้าใจได้ว่าเป็นข้อมูลที่อธิบายโปรแกรมอีกด้วย
exports、providers、imports、controllers ที่กำหนดค่าโดย @Module ใน Nest เป็นข้อมูล เมตา ทั้งหมด เนื่องจากเป็นข้อมูลที่ใช้เพื่ออธิบายความสัมพันธ์ของโปรแกรม ข้อมูลนี้ไม่ใช่ข้อมูลจริงที่แสดงต่อผู้ใช้ปลายทาง แต่ถูกอ่านและรับรู้โดย โปรแกรมกรอบงาน
4.2 Nest Decorator
หากคุณดูซอร์สโค้ดของมัณฑนากรใน Nest คุณจะพบว่ามัณฑนากรเกือบทุกคนจะกำหนดเมตาดาต้าผ่านการสะท้อนเมตาดาต้าเท่านั้น
@
ฟังก์ชั่นการส่งออกมัณฑนากร Injectable Injectable (ตัวเลือก?: InjectableOptions): ClassDecorator {
กลับ (เป้าหมาย: วัตถุ) => {
Reflect.defineMetadata (INJECTABLE_WATERMARK, จริง, เป้าหมาย);
Reflect.defineMetadata (SCOPE_OPTIONS_METADATA, ตัวเลือก, เป้าหมาย);
-
มีแนวคิดของการสะท้อนอยู่ที่นี่ และ
providers สะท้อนนั้นค่อนข้างง่ายที่จะเข้าใจ ใช้ @Module decorator เป็นตัวอย่างเพื่อกำหนด providers ข้อมูลเม providers โปรแกรมกรอบงานจะใช้โดยอัตโนมัติ การสร้างอินสแตนซ์จะกลายเป็นผู้ให้บริการ และนักพัฒนาไม่จำเป็นต้องดำเนินการสร้างอินสแตนซ์และการฉีดขึ้นต่อกันอย่างชัดเจน คลาสจะกลายเป็นผู้ให้บริการหลังจากสร้างอินสแตนซ์ในโมดูลเท่านั้น คลาสใน providers จะสะท้อนให้เห็นและกลายเป็นผู้ให้บริการ การผกผันของการควบคุมเป็นเทคโนโลยีการสะท้อนที่ใช้
อีกตัวอย่างหนึ่งคือ ORM (Object Relational Mapping) ในฐานข้อมูล หากต้องการใช้ ORM คุณเพียงแค่กำหนดฟิลด์ตาราง และไลบรารี ORM จะแปลงข้อมูลอ็อบเจ็กต์เป็นคำสั่ง SQL โดยอัตโนมัติ
ข้อมูล const = TableModel.build();
ข้อมูล.เวลา = 1;
ข้อมูล.เบราว์เซอร์ = 'โครเมี่ยม';
ข้อมูล.บันทึก();
// SQL: INSERT INTO tableName (time,browser) [{"time":1,"browser///chrome"}] ไลบรารี ORM ใช้เทคโนโลยีการสะท้อน ดังนั้นผู้ใช้จะต้องใส่ใจกับข้อมูลฟิลด์เท่านั้น และวัตถุคือการสะท้อนของไลบรารี ORM กลายเป็นคำสั่งดำเนินการ SQL นักพัฒนาจำเป็นต้องเน้นไปที่เขตข้อมูลเท่านั้นและไม่จำเป็นต้องเขียน SQL
4.3flect-metadata
สะท้อนเมตาดาต้าเป็นไลบรารีสะท้อนที่ Nest ใช้เพื่อจัดการข้อมูลเมตา flect-metadata ใช้ WeakMap เพื่อสร้างอินสแตนซ์เดียวทั่วโลก และตั้งค่าและรับข้อมูลเมตาของอ็อบเจ็กต์ที่ได้รับการตกแต่ง (คลาส วิธีการ ฯลฯ) ผ่านวิธีการตั้งค่าและรับ
// ลองดู var _WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();
ข้อมูลเมตา var = ใหม่ _WeakMap();
ฟังก์ชั่นกำหนด Metadata(){
OrdinaryDefineOwnMetadata(){
GetOrCreateMetadataMap(){
var targetMetadata = Metadata.get(O);
ถ้า (IsUnknown (targetMetadata)) {
ถ้า (!สร้าง)
กลับไม่ได้กำหนด;
targetMetadata = ใหม่ _Map();
Metadata.set(O, targetMetadata);
-
var metadataMap = targetMetadata.get(P);
ถ้า (IsUnknown (metadataMap)) {
ถ้า (!สร้าง)
กลับไม่ได้กำหนด;
metadataMap = ใหม่ _Map();
targetMetadata.set(P, metadataMap);
-
กลับ metadataMap;
-
-
} flect-metadata เก็บข้อมูลเมตาของบุคคลที่ได้รับการตกแต่งในอ็อบเจ็กต์ singleton ทั่วโลกเพื่อการจัดการแบบรวมศูนย์ การสะท้อนเมตาดาต้าไม่ได้ใช้การสะท้อนกลับที่เฉพาะเจาะจง แต่มีไลบรารีเครื่องมือเพื่อช่วยในการดำเนินการการสะท้อนกลับ
เรามาดูคำถามก่อนหน้านี้กัน
เหตุใดจึงต้องมีการผกผันการควบคุม?
การฉีดพึ่งพาคืออะไร?
มัณฑนากรทำอะไร?
หลักการดำเนินการของผู้ให้บริการ การนำเข้า และการส่งออกในโมดูล (@Module) คืออะไร
ความเห็นที่ 1 และ 2 ผมคิดว่าผมเคยอธิบายไว้ชัดเจนแล้ว หากยังคลุมเครืออยู่บ้าง แนะนำให้กลับไปอ่านอีกครั้งและอ่านบทความอื่นๆ เพื่อช่วยให้เข้าใจความรู้ผ่านการคิดของผู้เขียนหลายๆ คน
5.1 ปัญหา [3 4] ภาพรวม:
Nest ใช้เทคโนโลยีการสะท้อนเพื่อใช้การผกผันของการควบคุมและให้ความสามารถในการเขียนโปรแกรมเมตา นักพัฒนาใช้ @Module มัณฑนากรเพื่อตกแต่งคลาสและกำหนดข้อมูลเมตา (ผู้ให้บริการ นำเข้า ส่งออก) และข้อมูลเมตาจะถูกจัดเก็บไว้ในส่วนกลาง วัตถุ (ใช้ไลบรารีสะท้อนข้อมูลเมตา) หลังจากที่โปรแกรมทำงาน โปรแกรมควบคุมภายในกรอบงาน Nest จะอ่านและลงทะเบียนแผนผังโมดูล สแกนข้อมูลเมตาและสร้างอินสแตนซ์คลาสให้เป็นผู้ให้บริการ และจัดเตรียมไว้ในโมดูลทั้งหมดตามข้อกำหนดของผู้ให้บริการนำเข้าส่งออกในข้อมูลเมตาของโมดูล ค้นหาอินสแตนซ์ (ผู้ให้บริการ) ของคลาสที่ต้องพึ่งพาอื่นๆ ของคลาสปัจจุบัน และฉีดผ่าน Constructor หลังจากค้นหาแล้ว
บทความนี้มีแนวคิดมากมายและไม่ได้ให้การวิเคราะห์ที่ละเอียดเกินไป แนวคิดเหล่านี้ต้องใช้เวลาในการทำความเข้าใจอย่างช้าๆ หากยังไม่เข้าใจโดยละเอียดก็อย่ากังวลจนเกินไป บทความนี้ยังคงใช้ความพยายามอย่างมาก เพื่อนๆ ที่ชอบหวังว่าคุณจะสามารถเชื่อมต่อได้สามครั้งด้วยการคลิกเพียงครั้งเดียว~