ทำความเข้าใจกับนิพจน์ 'track by' ของ ngRepeat


102

ฉันมีปัญหาในการทำความเข้าใจว่าแทร็กโดยการแสดงออกของ ng-repeat ใน angularjs ทำงานอย่างไร เอกสารประกอบหายากมาก: http://docs.angularjs.org/api/ng/directive/ngRepeat

คุณสามารถอธิบายสิ่งที่แตกต่างระหว่างทั้งสองตัวอย่างของรหัสที่อยู่ในแง่ของdatabindingและด้านอื่น ๆ ที่เกี่ยวข้อง?

กับ: track by $index

<!--names is an array-->
<div ng-repeat="(key, value) in names track by $index">
  <input ng-model="value[key]">                         
</div>

ไม่มี (เอาต์พุตเดียวกัน)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>

คำถามดีๆพร้อมคำตอบที่ดีมาก! น่าเสียดายที่ OP ไม่ยอมรับคำตอบหรือคุณไม่คิดว่าคำถามนั้นตอบถูก?
Mawg กล่าวว่าคืนสถานะ Monica

คุณถูก! ฉันเพิ่งยอมรับคำตอบของ TJ
Jonathan Grupp

คำตอบ:


97

คุณสามารถทำได้track by $indexหากแหล่งข้อมูลของคุณมีตัวระบุที่ซ้ำกัน

เช่น: $scope.dataSource: [{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

คุณไม่สามารถทำซ้ำคอลเล็กชันนี้ได้ในขณะที่ใช้ "id" เป็นตัวระบุ (ซ้ำ id: 1)

จะไม่ทำงาน:

<element ng-repeat="item.id as item.name for item in dataSource">
  // something with item ...
</element>

แต่คุณสามารถทำได้หากใช้track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>

1
ขอบคุณสำหรับคำตอบ! แต่แน่นอนว่าตัวระบุที่ซ้ำกันไม่ได้เป็นเพียงกรณีใช้งานเท่านั้น นอกจากนี้ฉันต้องการทราบว่าเกิดอะไรขึ้น 'ภายใต้ประทุน'
Jonathan Grupp

2
มันง่ายมากแค่ดูโค้ดมันเป็นโอเพ่นซอร์สทั้งหมด;)
nilsK

4
คำถามนี้เก่า แต่ฉันยังคิดว่าอาจช่วยให้เข้าใจ bennadel.com/blog/…คำอธิบายสั้น ๆ ที่นี่ docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D

3
อีกสิ่งหนึ่งที่ต้องคำนึงถึงคือหากคุณสามารถใช้การติดตามทีละคีย์คุณจะได้รับประสิทธิภาพที่ดีขึ้น (blog.500tech.com/is-reactjs-fast) คุณลักษณะนี้ช่วยให้คุณสามารถเชื่อมโยงวัตถุ JavaScript กับโหนด ngRepeat DOM (Document Object Model) โดยใช้ตัวระบุเฉพาะ ด้วยการเชื่อมโยงนี้ AngularJS จะไม่ $ ทำลายและสร้างโหนด DOM ขึ้นใหม่โดยไม่จำเป็น สิ่งนี้สามารถมีประสิทธิภาพและประโยชน์อย่างมากต่อประสบการณ์ของผู้ใช้ ( bennadel.com/blog/… )
Braulio

ฉันมีรายการแปลก ๆ 700 รายการ เวลาในการแสดงผลเปลี่ยนไปจาก 4 วินาทีเป็น 100 มิลลิวินาที ควรใช้ Track by สำหรับ ngRepeat ทั้งหมดตามข้อมูลที่มาจากส่วนที่เหลือ
Patrick

60

สรุปสั้น ๆ :

track by ใช้เพื่อเชื่อมโยงข้อมูลของคุณกับการสร้าง DOM (และส่วนใหญ่สร้างใหม่) ที่ทำโดย ng-repeat

เมื่อคุณเพิ่มtrack byโดยพื้นฐานแล้วคุณบอกเชิงมุมเพื่อสร้างองค์ประกอบ DOM เดียวต่อวัตถุข้อมูลในคอลเลกชันที่กำหนด

สิ่งนี้อาจมีประโยชน์เมื่อทำการเพจและกรองหรือกรณีใด ๆ ที่มีการเพิ่มหรือลบอ็อบเจ็กต์ออกจากng-repeatรายการ

โดยปกติการไม่มีtrack byเชิงมุมจะเชื่อมโยงวัตถุ DOM กับคอลเล็กชันโดยการฉีดคุณสมบัติ expando - $$hashKey- ลงในวัตถุ JavaScript ของคุณและจะสร้างใหม่ (และเชื่อมโยงวัตถุ DOM อีกครั้ง) กับการเปลี่ยนแปลงทุกครั้ง

คำอธิบายแบบเต็ม:

http://www.bennadel.com/blog/2556-using-track-by-with-ngrepeat-in-angularjs-1-2.htm

คำแนะนำที่เป็นประโยชน์เพิ่มเติม:

http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

(ติดตามได้ในเชิงมุม> 1.2)


8

หากคุณกำลังทำงานกับอ็อบเจ็กต์ที่ติดตามโดยตัวระบุ (เช่น $ index) แทนอ็อบเจ็กต์ทั้งหมดและคุณโหลดข้อมูลของคุณซ้ำในภายหลัง ngRepeat จะไม่สร้างองค์ประกอบ DOM ใหม่สำหรับไอเท็มที่แสดงผลไปแล้วแม้ว่าอ็อบเจ็กต์ JavaScript ในคอลเล็กชันจะมี ถูกเปลี่ยนตัวใหม่


การอ้างอิงใด ๆ ที่พิสูจน์สิ่งนี้?
azerafati

มีวิธีบังคับให้เรนเดอร์ไหม หรืองานอื่น ๆ ? ฉันไม่พบสิ่งนี้ที่กล่าวถึงที่ไหน แต่ฉันเชื่อว่านี่คือสิ่งที่สร้างความยุ่งเหยิงให้ฉันและฉันเสียเวลาไปมากแล้ว
NeverGiveUp161

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