عرض القوائم الضخمة بكفاءة ومفهوم Virtualization
| الخاصية | العرض التقليدي (Standard Rendering) | العرض الافتراضي (List Virtualization) |
|---|---|---|
| عدد عناصر الـ DOM المنشأة | يساوي إجمالي عدد عناصر القائمة كلياً (مثلاً 10000 عنصر HTML) | يساوي فقط عدد العناصر الظاهرة في الشاشة حالياً (مثلاً 10 عناصر) |
| استهلاك الذاكرة (Memory Usage) | مرتفع جداً ويسبب إبطاء متزايد للمتصفح والصفحة | منخفض جداً وثابت مهما زاد حجم القائمة في السيرفر |
| سرعة الاستجابة والتمرير (Scrolling) | تقطيع وثقل ملحوظ أثناء التمرير السريع (Jank) | تمرير سلس وسريع بفريد حركة 60fps بدون أي تأخير |
| الآلية البرمجية | رندرة جميع العناصر دفعة واحدة باستخدام map | احتساب مساحة التمرير (Scroll Position) ورندرة ما يراه المستخدم فقط |
عندما تقوم برندرة مصفوفة تحتوي على آلاف العناصر (مثل قائمة الدروس، الطلاب، أو سجلات النظام) باستخدام الدالة الشهيرة map()، يقوم المتصفح بإنشاء عنصر DOM حقيقي لكل عنصر داخل المصفوفة.
تضخم شجرة الـ DOM بآلاف العناصر يستهلك ذاكرة المتصفح بسرعة، ويؤدي إلى استجابة بطيئة للواجهة وتقطيع مزعج أثناء السكرول (Laggy Scrolling).
تقوم فكرة الـ Virtualization على مبدأ ذكي جداً: لماذا نرندر 10,000 عنصر في شجرة الـ DOM بينما لا يستطيع المستخدم رؤية سوى 10 عناصر فقط في شاشة هاتف أو كمبيوتر؟ بدلاً من رندرة القائمة الكاملة، تنشئ هذه التقنية "نافذة افتراضية" (Virtual Window) ترندر فقط العناصر المرئية حالياً داخل حدود الشاشة (Viewport)، بالإضافة لعنصرين قبلها وبعدها لتوفير سكرول ناعم. وعندما يمرر المستخدم لأسفل، يتم استبدال محتوى العناصر فوراً وإعادة استخدام نفس وسم الـ HTML!
بدلاً من كتابة معادلات الأبعاد والأوفسيت اليدوية المجهزة بالأخطاء، تعتمد الأوساط الاحترافية على مكتبات متخصصة فائقة الخفة مثل react-window أو react-virtualized.
| 1 | // كود يسبب ثقل المتصفح عند وجود 10,000 عنصر |
| 2 | function HeavyList({ items }) { |
| 3 | return ( |
| 4 | <ul> |
| 5 | {items.map((item) => ( |
| 6 | <li key={item.id}>{item.name}</li> |
| 7 | ))} |
| 8 | </ul> |
| 9 | ); |
| 10 | } |
| 1 | import { FixedSizeList as List } from 'react-window'; |
| 2 | |
| 3 | // مكون الفرعي لرندرة السطر الواحد |
| 4 | const Row = ({ index, style, data }) => ( |
| 5 | <div style={style} className="list-item"> |
| 6 | {data[index].name} |
| 7 | </div> |
| 8 | ); |
| 9 | |
| 10 | function VirtualizedList({ items }) { |
| 11 | return ( |
| 12 | <List |
| 13 | height={400} // ارتفاع النافذة الظاهرة بالبكسل |
| 14 | itemCount={items.length} // إجمالي عدد العناصر (حتى لو مليون!) |
| 15 | itemSize={50} // ارتفاع العنصر الواحد بالبكسل |
| 16 | width="100%" // عرض القائمة |
| 17 | itemData={items} // تمرير البيانات المباشرة |
| 18 | > |
| 19 | {Row} |
| 20 | </List> |
| 21 | ); |
| 22 | } |
إلى جانب الـ Virtualization، هناك ممارسات هندسية تضمن الحفاظ على السرعة الفائقة: