เมื่อคุณพัฒนาแอปพลิเคชันที่ใช้ส่วนประกอบขนาดใหญ่ ซึ่งมักจะสื่อสารและรับข้อมูลจากเซิร์ฟเวอร์ โครงสร้างของเพจ คุณสมบัติ และส่วนประกอบอาจขึ้นอยู่กับข้อมูลที่คุณได้รับโดยธรรมชาติ
หากคุณโมดูลส่วนประกอบของคุณเป็นหน่วยอิสระขนาดเล็ก โดยแต่ละหน่วยรับผิดชอบพื้นที่หรือส่วนหนึ่งในเพจของคุณ คุณอาจมี 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`
- การสร้างและองค์ประกอบเชิงมุม
- รวบรวมองค์ประกอบและรับฟังก์ชันลิงก์
- การสร้างขอบเขตพี่น้องใหม่
- กำหนดการเชื่อมโยงให้กับขอบเขตใหม่
- เชื่อมโยงขอบเขตใหม่กับมุมมอง
- ผนวกองค์ประกอบเข้ากับพาเรนต์
- ทำลายขอบเขตเก่า
- ลบองค์ประกอบเก่าออก
ตอนนี้เรามีส่วนประกอบใหม่โดยไม่ต้องประกาศอย่างชัดเจน และคุณมีการพึ่งพากล่องดำขนาดเล็กของคุณเองเพื่อดำเนินการกับความท้าทายครั้งต่อไปใน AngularJS ซึ่งแน่นอนว่าถ้าคุณยังคงใช้งานอยู่