ความแตกต่างระหว่างฟังก์ชั่น 'คอนโทรลเลอร์', 'ลิงค์' และ 'คอมไพล์' เมื่อกำหนดไดเรกทีฟ


393

บางแห่งดูเหมือนว่าจะใช้ฟังก์ชั่นควบคุมสำหรับตรรกะคำสั่งและอื่น ๆ ใช้ลิงค์ ตัวอย่างแท็บบนโฮมเพจเชิงมุมใช้คอนโทรลเลอร์สำหรับหนึ่งและลิงก์สำหรับคำสั่งอื่น ความแตกต่างระหว่างสองคืออะไร?


2
บางทีอาจจะเป็นภาพรวมที่ครอบคลุมมากขึ้นของฟังก์ชั่นสั่ง: สั่งเชิงมุม - เมื่อจะใช้รวบรวมควบคุมก่อนการเชื่อมโยงและการโพสต์ลิงค์
Izhaki

คำตอบ:


635

ฉันจะขยายคำถามของคุณเล็กน้อยและรวมถึงฟังก์ชั่นการคอมไพล์

  • ฟังก์ชั่นการคอมไพล์ - ใช้สำหรับการจัดการ DOM แม่แบบ (เช่นการจัดการขององค์ประกอบ tElement = เท็มเพลต) ดังนั้นการจัดการที่ใช้กับ DOM clones ทั้งหมดของเทมเพลตที่เกี่ยวข้องกับคำสั่ง (หากคุณต้องการฟังก์ชันลิงก์ (หรือฟังก์ชันก่อนและหลังลิงก์ลิงก์) และคุณได้กำหนดฟังก์ชันการคอมไพล์ฟังก์ชันการคอมไพล์จะต้องส่งคืนฟังก์ชันลิงก์เนื่องจาก'link'แอตทริบิวต์นั้นถูกละเว้นหาก'compile'มีการกำหนดแอตทริบิวต์)

  • ฟังก์ชั่นการเชื่อมโยง - โดยปกติจะใช้สำหรับการลงทะเบียนการเรียกกลับ (เช่น$watchการแสดงออกในขอบเขต) เช่นเดียวกับการปรับปรุง DOM (เช่นการจัดการของ iElement = องค์ประกอบอินสแตนซ์ของแต่ละบุคคล) มันจะดำเนินการหลังจากที่แม่แบบได้รับการโคลน ตัวอย่างเช่นภายใน<li ng-repeat...>ฟังก์ชันลิงก์จะถูกดำเนินการหลังจาก<li>เทมเพลต (tElement) ถูกโคลน (เป็น iElement) สำหรับ<li>องค์ประกอบนั้น ๆ $watchช่วยให้คำสั่งจะได้รับการแจ้งการเปลี่ยนแปลงสถานที่ให้บริการขอบเขต (ขอบเขตที่มีความเกี่ยวข้องกับแต่ละกรณี) ซึ่งช่วยให้คำสั่งที่จะทำให้ค่าเช่นการปรับปรุงเพื่อ DOM

  • ฟังก์ชั่นควบคุม - จะต้องใช้เมื่อคำสั่งอื่นต้องการโต้ตอบกับคำสั่งนี้ ตัวอย่างเช่นในหน้าแรกของ AngularJS คำสั่งบานหน้าต่างจำเป็นต้องเพิ่มตัวเองในขอบเขตที่ดูแลโดยคำสั่งของแท็บดังนั้นคำสั่งของแท็บจำเป็นต้องกำหนดวิธีการควบคุม (คิดว่า API) ที่คำสั่งบานหน้าต่างสามารถเข้าถึง / โทรได้

    สำหรับคำอธิบายเพิ่มเติมในเชิงลึกของแท็บและสั่งบานหน้าต่างและทำไมแท็บคำสั่งสร้างฟังก์ชั่นในตัวควบคุมที่ใช้this(มากกว่า$scope) โปรดดู'นี้' VS $ ขอบเขตในการควบคุม

โดยทั่วไปคุณสามารถใส่เมธอด$watchesและอื่น ๆ ลงในคอนโทรลเลอร์หรือฟังก์ชั่นลิงค์ของไดเรกทีฟ ตัวควบคุมจะทำงานก่อนซึ่งบางครั้งสำคัญ (ดูซอที่บันทึกเมื่อฟังก์ชั่น ctrl และลิงค์ทำงานด้วยสองคำสั่งซ้อนกัน) ดังที่ Josh กล่าวไว้ในความคิดเห็นคุณอาจต้องการใส่ฟังก์ชั่นการปรับขอบเขตในตัวควบคุมเพื่อความสอดคล้องกับส่วนที่เหลือของเฟรมเวิร์ก


131
คำอธิบายนี้ควรอยู่ในเอกสารหลักของ AngularJS หรืออย่างน้อยก็มีการอ้างถึง
Dogoku

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

$ compiler จะละเว้นแอตทริบิวต์ 'link' ต่อหน้าแอตทริบิวต์ 'compile' แต่สิ่งที่เกี่ยวกับการปรากฏตัวของคุณลักษณะ 'ควบคุม'? 'คอนโทรลเลอร์' เป็นสาเหตุให้คอมไพเลอร์ $ เพิกเฉยต่อแอตทริบิวต์ 'ลิงก์' และ 'รวบรวม' อย่างใดอย่างหนึ่งหรือไม่? เป็นไปได้และ / หรือแนะนำให้ใช้ 'คอมไพล์' ร่วมกับ 'คอนโทรลเลอร์' หรือไม่?
Carl G

1
@CarlG การมีอยู่ของแอ็ตทริบิวต์คอนโทรลเลอร์ไม่มีผลต่อ $ คอมไพเลอร์เกี่ยวกับลิงค์และคอมไพล์ คุณสามารถใช้คอมไพล์และคอนโทรลเลอร์
Mark Rajcok

1
"ผู้ฟัง DOM" ไม่ใช่ "(เช่น $ watch expressions บนขอบเขต)" หนึ่งฟัง DOM สำหรับเหตุการณ์เช่นmouseoverอีกขอบเขตหนึ่งสำหรับการเปลี่ยนแปลงคุณสมบัติ แตกต่างใหญ่
Dmitri Zaitsev

56

ฟังก์ชั่นการคอมไพล์ไม่มีสิทธิ์เข้าถึงขอบเขต แต่เป็นฟังก์ชันเสริม

ฉันแนะนำวิดีโอนี้จริงๆ เขียนคำสั่งโดย Misko Hevery (บิดาแห่ง AngularJS) ซึ่งเขาอธิบายความแตกต่างและเทคนิคบางอย่าง (ความแตกต่างระหว่างฟังก์ชั่นการคอมไพล์และฟังก์ชั่นลิงค์ที่เครื่องหมาย 14:41 ในวิดีโอ )


3
+1 สำหรับลิงก์ไปยังวิดีโอ มันมีข้อมูลมาก
Rob Kielty


35
  1. ใช้รหัสก่อนคอมไพล์: ใช้คอนโทรลเลอร์
  2. ใช้รหัสหลังจากรวบรวม: ใช้ลิงค์

ระเบียบการเชิงมุม: เขียนตรรกะทางธุรกิจในคอนโทรลเลอร์และการจัดการ DOM ในลิงก์

นอกเหนือจากนี้คุณสามารถเรียกใช้ฟังก์ชันคอนโทรลเลอร์หนึ่งฟังก์ชันจากลิงก์ฟังก์ชันของคำสั่งอื่นตัวอย่างเช่นคุณมี 3 คำสั่งที่กำหนดเอง

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>

และคุณต้องการเข้าถึงสัตว์จากภายในของคำสั่ง "เสือดาว"

http://egghead.io/lessons/angularjs-directive-communicationจะเป็นประโยชน์ที่จะทราบเกี่ยวกับการสื่อสารระหว่างคำสั่ง


18
"ใช้รหัสก่อนคอมไพล์: ใช้คอนโทรลเลอร์". สิ่งนี้ไม่ถูกต้อง compileจะถูกดำเนินการก่อน controllerเสมอ
Izhaki

คุณจะไม่สามารถเข้าถึงสัตว์ได้จากคำสั่งเสือดาวของคุณ (อย่างน้อยก็ไม่ใช่ในทางที่ตรงไปตรงมา) ไดเรกทีฟลูกสามารถเข้าถึงเมธอดคอนโทรลเลอร์ในไดเรกทีฟไดเรกทีฟ แต่ไดเรกทีฟ sibling (เช่นในตัวอย่างด้านบน) ไม่สามารถเรียกคอนโทรลเลอร์ของอีกฝ่ายได้
Benjamin White

2
เสือดาวเป็นเสือจริงๆหรือ? นอกจากนี้ในบันทึกด้านข้าง ... คุณมีลิงค์ - และ - คอนโทรลเลอร์ในทิศทางได้หรือไม่?
โคดี้

1
ใช่เสือดาว / เสือจากัวร์เป็นแพนเทอร์ และใช่คุณมีลิงค์และตัวควบคุมภายในคำสั่ง
ราหุล

1
จากคู่มือนักพัฒนาเชิงมุม: "แนวทางปฏิบัติที่ดีที่สุด: ใช้คอนโทรลเลอร์เมื่อคุณต้องการเปิดเผย API ไปยังคำสั่งอื่น ๆ มิฉะนั้นให้ใช้ลิงก์"
Martin van Driel

6

ฟังก์ชั่นการรวบรวม -

  1. ถูกเรียกก่อนฟังก์ชันควบคุมและลิงก์
  2. ในฟังก์ชั่นการคอมไพล์คุณมี DOM เทมเพลตดั้งเดิมเพื่อให้คุณสามารถทำการเปลี่ยนแปลงใน DOM ดั้งเดิมก่อน AngularJS จะสร้างอินสแตนซ์ของมันและก่อนที่จะสร้างขอบเขต
  3. ng-repeat เป็นตัวอย่างที่สมบูรณ์แบบ - ไวยากรณ์ดั้งเดิมคือองค์ประกอบแม่แบบองค์ประกอบที่ทำซ้ำใน HTML เป็นอินสแตนซ์
  4. สามารถมีได้หลายอินสแตนซ์องค์ประกอบและองค์ประกอบองค์ประกอบเดียวเท่านั้น
  5. ขอบเขตยังไม่พร้อมใช้งาน
  6. ฟังก์ชันการคอมไพล์สามารถส่งคืนฟังก์ชันและวัตถุได้
  7. ส่งคืนฟังก์ชั่น (post-link) - เทียบเท่ากับการลงทะเบียนฟังก์ชั่นการเชื่อมโยงผ่านทางลิงค์คุณสมบัติของวัตถุการกำหนดค่าเมื่อฟังก์ชั่นการคอมไพล์ว่างเปล่า
  8. ส่งคืนวัตถุที่มีฟังก์ชั่นที่ลงทะเบียนผ่านคุณสมบัติก่อนและหลังการโพสต์ - ช่วยให้คุณสามารถควบคุมได้ว่าควรจะเรียกฟังก์ชั่นการเชื่อมโยงเมื่อใดในช่วงเฟสการลิงก์ ดูข้อมูลเกี่ยวกับฟังก์ชั่นการลิงก์ล่วงหน้าและการโพสต์ลิงก์ด้านล่าง

วากยสัมพันธ์

function compile(tElement, tAttrs, transclude) { ... }

ตัวควบคุม

  1. เรียกว่าหลังจากฟังก์ชั่นการรวบรวม
  2. ขอบเขตมีให้ที่นี่
  3. สามารถเข้าถึงได้โดยคำสั่งอื่น ๆ (ดูต้องการคุณลักษณะ)

ลิงก์ล่วงหน้า

  1. ฟังก์ชั่นลิงค์มีหน้าที่ในการลงทะเบียนผู้ฟัง DOM และอัปเดต DOM มันจะดำเนินการหลังจากที่แม่แบบได้รับการโคลน นี่คือจุดที่ตรรกะส่วนใหญ่จะถูกวาง

  2. คุณสามารถอัพเดท dom ในคอนโทรลเลอร์ได้โดยใช้ angular.element แต่ไม่แนะนำเนื่องจากองค์ประกอบมีให้ในฟังก์ชั่นลิงค์

  3. ฟังก์ชั่นการเชื่อมโยงล่วงหน้าใช้ในการสร้างลอจิกที่ทำงานเมื่อแองกูลาร์ js ได้ทำการรวบรวมองค์ประกอบลูก แต่ก่อนที่จะมีการเรียกลิงค์โพสต์ขององค์ประกอบลูกใด ๆ

โพสต์ลิงก์

  1. คำสั่งที่มีฟังก์ชั่นเชื่อมโยงเท่านั้นมุมเชิงปฏิบัติหน้าที่เป็นลิงค์โพสต์

  2. โพสต์จะถูกดำเนินการหลังจากคอมไพล์คอนโทรลเลอร์และ pre-link funciton ดังนั้นนี่จึงเป็นเหตุผลว่าทำไมสถานที่ที่ปลอดภัยที่สุดและเป็นค่าเริ่มต้นเพื่อเพิ่มตรรกะคำสั่งของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.