เมื่อคุณพัฒนาแอปพลิเคชันที่ใช้ส่วนประกอบขนาดใหญ่ ซึ่งมักจะสื่อสารและรับข้อมูลจากเซิร์ฟเวอร์ โครงสร้างของเพจ คุณสมบัติ และส่วนประกอบอาจขึ้นอยู่กับข้อมูลที่คุณได้รับโดยธรรมชาติ

หากคุณโมดูลส่วนประกอบของคุณเป็นหน่วยอิสระขนาดเล็ก โดยแต่ละหน่วยรับผิดชอบพื้นที่หรือส่วนหนึ่งในเพจของคุณ คุณอาจมี package.json ที่เต็มไปด้วยการขึ้นต่อกัน โดยส่วนใหญ่แล้ว ยกเว้นส่วนประกอบ 'คงที่' ที่คุณประกาศ แอปพลิเคชันของคุณจะรู้ว่าองค์ประกอบใดที่จะแสดงผลใน 'รันไทม์' ตามตรรกะที่คุณนำไปใช้และข้อมูลที่ได้รับจากเซิร์ฟเวอร์

วิธีหนึ่งในการบรรลุเป้าหมายคือการแสดงรายการส่วนประกอบทั้งหมดด้วยคำสั่ง ng-if แบบมีเงื่อนไข คุณอาจจบลงด้วยรายการการขึ้นต่อกันทั้งหมดที่น่าเบื่อไม่รู้จบที่คุณระบุไว้ใน package.json ของแอปพลิเคชันของคุณ นั่นไม่ใช่แนวทางปฏิบัติที่ดีอย่างแน่นอน ยกเว้นในกรณีที่คุณควรใช้ ng-if โค้ดของคุณกลายเป็นแบบคงที่และยาว และส่วนสำคัญของโค้ดก็ไม่ได้ถูกใช้ด้วยซ้ำในที่สุด คุณอาจระบุส่วนประกอบที่มีเงื่อนไขยี่สิบรายการเพื่อจบลงด้วยการใช้เพียงส่วนประกอบเดียวเท่านั้น มีวิธีที่ดีกว่า เจ๋งและเรียบร้อยในการทำสิ่งนี้โดยใช้เครื่องมือที่ยอดเยี่ยมของ AngularJS, $compile

การใช้ $compile เราสามารถสร้างเนื้อหาใหม่แบบไดนามิกในแอปพลิเคชัน AngularJS ฉันจะนำเสนอวิธีหนึ่งในการบรรลุผลสำเร็จโดยการบรรจุโซลูชันเป็นโมดูลสิ้นเปลืองอิสระขนาดเล็ก

ก่อนอื่น มาสร้างส่วนประกอบง่ายๆ `select-items` กันก่อน เราจะใช้มันในตัวอย่างของฉันในภายหลัง

เลือกรายการ.html:

ที่นี่เรามีองค์ประกอบ select แบบเลื่อนลงง่ายๆ ที่ยอมรับรายการวัตถุที่มีคุณสมบัติ `ชื่อ` เพื่อแสดงในแต่ละตัวเลือกที่ ng-options จะสร้างภายใน <select> เมื่อใดก็ตามที่รายการถูกเลือก ng-change จะเรียกใช้เมธอด onSelect ในคอนโทรลเลอร์ `select-items` ด้านล่างและส่งผ่านไปยังออบเจ็กต์ที่เลือก

เลือกรายการ js:

คำสั่ง `select-items` ถูกจำกัดให้เป็นองค์ประกอบ เมื่อเรียก `onSelect` แล้ว การโทรกลับ onItemSelected จะถูกทริกเกอร์เพื่ออัปเดตคอนซูเมอร์ของ <select-items> ด้วยออบเจ็กต์ที่เลือกใหม่

แอพ js:

ใน app.js เราตั้งค่าอาร์เรย์ โดยแสดงรายการส่วนประกอบทั้งหมดที่เราต้องการรวบรวมแบบไดนามิกในรูปแบบอ็อบเจ็กต์ เพื่อเป็นตัวอย่าง เราใช้เพียงอันเดียวเท่านั้น มันมีคุณสมบัติสองประการ: `name` — ชื่อของคำสั่งที่คอมไพล์ใหม่ให้เป็น และ `bindings` — เราสามารถกำหนดขอบเขตใหม่ที่เราคอมไพล์อะไรก็ได้ที่เราต้องการ: การเรียกกลับ วัตถุ และข้อมูลเบื้องต้น นอกจากนี้เรายังสามารถเพิ่มคุณสมบัติ `orderBy` เพื่อควบคุมลำดับว่าคำสั่งในอนาคตของเราจะถูกรวบรวมและเพิ่มลงในมุมมอง

ดัชนี.html:

มาถึงส่วนที่น่าสนใจแล้ว เราได้ประกาศคำสั่งแบบกำหนดเอง <compile-me> ที่สร้างขึ้นซ้ำ ๆ ด้วย ng-repeat สำหรับแต่ละวัตถุที่สร้างคำสั่งแบบกำหนดเองที่เราส่งผ่านไปใน Consumer Controller app.js

คอมไพล์-me.js

มาอธิบายสิ่งที่เกิดขึ้นในคอนโทรลเลอร์ <compile-me> กัน ใน บรรทัดที่ 1 ฉันส่งเทมเพลตไปที่ ``เชิงมุม.องค์ประกอบ()` ซึ่งเป็นชื่อของคำสั่ง <select-items> ที่เราตั้งไว้ใน `customDirectives` อาร์เรย์ที่ฉันส่งผ่านไปยังคำสั่ง <compile-me> ค่าที่ส่งคืน $el ตอนนี้เป็น "องค์ประกอบเชิงมุม"

ใน บรรทัดที่ 2 องค์ประกอบเชิงมุม $el จะถูกส่งผ่านไปยัง $compile คอมไพล์เป็นฟังก์ชันภายในคำสั่ง การจัดการ DOM การเพิ่มหรือการลบคำสั่งและองค์ประกอบ DOM อื่นๆ เสร็จสิ้นในฟังก์ชันคอมไพล์ก่อนที่กระบวนการ `postLink` จะเริ่มต้นขึ้น การคอมไพล์เป็นหนึ่งในสี่ฟังก์ชันที่เกิดขึ้นในวงจรชีวิตของคำสั่ง:

$compile เดินผ่านแผนผัง DOM โดยเริ่มต้นที่องค์ประกอบเชิงมุมของเรา และไป ซ้ำๆ จากบนลงล่าง และจับคู่องค์ประกอบ DOM กับคำสั่ง คำสั่งทั้งหมดที่ค้นพบนั้นจะถูกรวบรวมเช่นกัน และฟังก์ชันลิงก์ (preLink, postLink) จะถูกรวบรวมและห่อด้วยฟังก์ชันลิงก์เดียวกันและส่งคืน

มีการดำเนินการสองฟังก์ชันสำหรับแต่ละคำสั่งที่ $compile ค้นพบ ได้แก่ controller และ preLink และดำเนินการซ้ำ จากบนลงล่าง ฟังก์ชันสุดท้าย postLink จะถูกดำเนินการสำหรับแต่ละคำสั่ง จากล่างขึ้นบน

ฟังก์ชัน controller ได้รับการสร้างอินสแตนซ์ก่อนขั้นตอนการเชื่อมโยงล่วงหน้า และสามารถเข้าถึงได้โดยคำสั่งอื่น จะช่วยให้การสื่อสารระหว่างคำสั่ง คำสั่งพี่น้องสามารถขอตัวควบคุมของพี่น้องได้ และคำสั่งย่อยสามารถขอตัวควบคุมของผู้ปกครองได้

preLink ดำเนินการก่อนที่องค์ประกอบลูกจะเชื่อมโยงกับมุมมอง ที่นี่เราสามารถจัดการ `$scope` ส่วนตัวก่อนที่จะเชื่อมโยงกับมุมมอง และกระบวนการ postLink จะเริ่มต้นขึ้น

ตอนนี้ เมื่อเราอยู่ที่ด้านล่างของแผนผัง DOM กระบวนการ postLink จะเริ่มต้นขึ้น ทำให้เกิดฟองขึ้นบนแผนผังและดำเนินการสำหรับแต่ละคำสั่ง จริงๆ แล้วมันคือชวเลขของฟังก์ชัน link() ที่ใช้บ่อยที่สุด มีหน้าที่รับผิดชอบในการลงทะเบียนผู้ฟัง DOM ตลอดจนอัปเดต DOM

ลำดับการดำเนินการของฟังก์ชันคำสั่ง:

คอมไพล์: คำสั่งบน → ล่าง

คอนโทรลเลอร์ & พรีลิงก์: คำสั่งบน → ล่าง

postLink: ด้านล่าง → คำสั่งด้านบน

ใน บรรทัดที่ 3 เราสร้างขอบเขตใหม่ `$newScope` และมันแสดงถึงขอบเขตใหม่สำหรับองค์ประกอบใหม่ <select-items> ที่ `compileMe` คอมไพล์ให้เราในการวนซ้ำปัจจุบัน ของ `ng-ทำซ้ำ` เราทำสิ่งนั้นสำเร็จโดยการเรียก $scope.$parent.$new() โดยการทำเช่นนี้ เราจะเพิ่มขอบเขตใหม่ต่อท้ายขอบเขตหลักของ `compileMe` ทำให้พวกมันเป็นพี่น้องกับพาเรนต์ในแผนผังขอบเขต หลังจากนั้นเราจะทำลายขอบเขตของ `compileMe` และลบตัวยึดตำแหน่งออกจาก DOM เพื่อให้กระบวนการสลับระหว่างสองคำสั่งเสร็จสมบูรณ์

ใน บรรทัดที่ 4 เราเพียงกำหนดคุณสมบัติทั้งหมดและค่าของมันจากส่วน `การเชื่อมโยง` ของออบเจ็กต์ `customDirectives` ให้กับ $newScope วัตถุ.

ต่อไป เราจะลิงก์ $newScope กับมุมมอง โดยส่งผ่านฟังก์ชัน `link` ที่เราตั้งค่าไว้ในบรรทัดที่ 2

ในบรรทัดต่อไปนี้ เราจะเพิ่มองค์ประกอบใหม่ที่เราสร้างไว้ต่อท้ายแผนผัง DOM ภายใต้องค์ประกอบหลักของ <compile-me> ทำให้พวกมันเป็นพี่น้องกัน ตอนนี้เมื่อเราใช้ <compile-me> เสร็จแล้ว เราอยากจะกล่าวขอบคุณและกำจัดมันออกไป ทั้งจากขอบเขตและแผนผัง DOM

การเรียก $scope.$destroy จะป้องกันไม่ให้ตัวจัดการเหตุการณ์ Angular เริ่มทำงาน เช่นเดียวกับการเผยแพร่เหตุการณ์ `$destroy` ในขอบเขตและขอบเขตลูกทั้งหมด $element.remove() ลบตัวยึดตำแหน่งออกจาก DOM

กระบวนการนี้จะถูกทำซ้ำสำหรับแต่ละรายการที่เราเพิ่มลงในออบเจ็กต์ `customDirectives`

  1. การสร้างและองค์ประกอบเชิงมุม
  2. รวบรวมองค์ประกอบและรับฟังก์ชันลิงก์
  3. การสร้างขอบเขตพี่น้องใหม่
  4. กำหนดการเชื่อมโยงให้กับขอบเขตใหม่
  5. เชื่อมโยงขอบเขตใหม่กับมุมมอง
  6. ผนวกองค์ประกอบเข้ากับพาเรนต์
  7. ทำลายขอบเขตเก่า
  8. ลบองค์ประกอบเก่าออก

ตอนนี้เรามีส่วนประกอบใหม่โดยไม่ต้องประกาศอย่างชัดเจน และคุณมีการพึ่งพากล่องดำขนาดเล็กของคุณเองเพื่อดำเนินการกับความท้าทายครั้งต่อไปใน AngularJS ซึ่งแน่นอนว่าถ้าคุณยังคงใช้งานอยู่