الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
Optimizing بالعربي

List Virtualization للمتوسط: اعرض 10,000 صف بدون ما المتصفح يتجمّد

متوسط21 يونيو 20264 دقائق قراءة
List Virtualization للمتوسط: اعرض 10,000 صف بدون ما المتصفح يتجمّد

هذا المقال يتطلب مستوى: متوسط

List Virtualization: اعرض 10,000 صف بدون ما المتصفح يتجمّد

لو عندك جدول أو قائمة فيها آلاف الصفوف والتمرير بيتقطّع، انت مش محتاج جهاز أقوى. المشكلة إنك بترسم كل العناصر في الـ DOM دفعة واحدة. الـ List Virtualization بيرسم اللي ظاهر قدام المستخدم بس، فيرجّع التمرير سلس عند 60 إطار في الثانية.

المشكلة باختصار

تخيّل صفحة بتعرض 10,000 منتج أو 10,000 صف لوج. المتصفح بيبني 10,000 عنصر DOM، وكل عنصر له تكلفة في الذاكرة وفي حساب التخطيط (layout). النتيجة: التمرير بيتهنّج، والكتابة في أي input بتتأخر. ده اللي بيحصل فعلاً لمّا الـ DOM يكبر أكتر من اللازم.

شاشة تعرض لوحة بيانات فيها صفوف ورسوم أداء كثيرة تمثل قائمة طويلة في واجهة ويب

المفهوم الأساسي: نافذة القطار

قبل التعريف العلمي، خد المثال ده. انت راكب في قطار وبتبصّ من الشباك. المنظر اللي برّه طوله 1000 كيلومتر، بس الشباك بيوريك 50 متر بس في كل لحظة. مش معقول تشوف الـ 1000 كيلومتر كلهم مرة واحدة، ومش محتاج. وانت ماشي، الشباك بيوريك الجزء الجديد ويخفي اللي عدّى.

الـ Virtualization بيشتغل بنفس الفكرة بالظبط. القائمة كلها 10,000 صف، بس "الشباك" (منطقة العرض الظاهرة) بتوري حوالي 20 صف. المكتبة بترسم الـ 20 دول بس، ووانت بتعمل scroll بتستبدلهم بصفوف جديدة بدل ما تبني الـ 10,000 من الأول.

التعريف العلمي: الـ List Virtualization (أو Windowing) تقنية بترسم في الـ DOM المجموعة الفرعية الظاهرة من العناصر فقط، مع buffer صغير، وتحدّث محتوى هذه العناصر مع التمرير بدل إنشاء عقدة DOM لكل عنصر. النتيجة عدد ثابت من عقد الـ DOM مهما كبر طول القائمة.

ليه القائمة الكبيرة بتجمّد المتصفح

الـ main thread في المتصفح بيعمل JavaScript وحساب الأنماط والتخطيط والرسم، كله على خيط واحد. عند 60fps عندك 16.66 مللي ثانية لكل إطار عشان تخلّص كل ده. أي مهمة بتاخد أكتر من 50 مللي ثانية بتتصنّف Long Task، وده اللي بيبان للمستخدم على شكل تقطيع (jank) وتأخّر في الاستجابة.

لمّا ترسم 10,000 صف، كل تغيير في القائمة بيجبر المتصفح يعيد حساب تخطيط آلاف العناصر. الافتراض هنا إن عندك قائمة فعلاً كبيرة (أكتر من 50–100 عنصر متشابه)؛ تحت كده المشكلة مش موجودة أصلاً.

الحل: react-window في 4 خطوات

  1. ثبّت المكتبة: npm install react-window.
  2. استخدم FixedSizeList لو كل الصفوف ليها نفس الارتفاع — ده الأسرع لأن المكتبة مش محتاجة تحسب موضع كل صف.
  3. اعمل component للصف الواحد، وطبّق عليه الـ style اللي بتبعته المكتبة (مهم جداً للتموضع الصحيح).
  4. اضبط overscanCount لرسم صفوف إضافية فوق وتحت النافذة عشان تمنع وميض المساحة الفاضية وقت السحب السريع.
JSX
import { FixedSizeList } from 'react-window';

function Row({ index, style }) {
  // لازم تمرّر style جاي من المكتبة للتموضع الصحيح
  return (
    <div style={style} className="row">
      الصف رقم {index}
    </div>
  );
}

export default function BigList({ items }) {
  return (
    <FixedSizeList
      height={600}            // ارتفاع منطقة العرض بالـ px
      itemCount={items.length} // 10000 صف
      itemSize={40}          // ارتفاع كل صف ثابت بالـ px
      width="100%"
      overscanCount={5}      // صفوف إضافية فوق وتحت النافذة
    >
      {Row}
    </FixedSizeList>
  );
}

اللي بيحصل فعلاً بعد التغيير: عدد عقد الـ DOM بينزل من 10,000 لحوالي 20 صف ظاهر + الـ overscan. التمرير بيرجع من حالة التقطيع لـ 60fps، واستهلاك الذاكرة بيقل بشكل واضح لأنك مش ماسك آلاف العناصر في الذاكرة.

رسم بياني لأداء تطبيق ويب يوضح قياس عدد الإطارات في الثانية قبل وبعد التحسين

الـ trade-offs اللي لازم تعرفها

  • بتكسب: DOM ثابت الحجم، تمرير 60fps، وذاكرة أقل بكتير.
  • بتخسر: بحث المتصفح بـ Ctrl+F مش هيلاقي الصفوف غير الظاهرة، لأنها مش موجودة في الـ DOM أصلاً.
  • تكلفة الـ SEO: المحتوى غير المرسوم مش هيتقرأ من محركات البحث، فمتستخدمهوش لمحتوى محتاج فهرسة.
  • تعقيد الارتفاعات المتغيّرة: لو الصفوف ارتفاعها مختلف، هتحتاج VariableSizeList وقياس لكل صف، وده أبطأ وأعقد من FixedSizeList.

ملحوظة على overscanCount: زيادته بتمنع وميض الفراغ وقت السحب، لكن زيادته أكتر من اللازم بترسم عناصر زيادة وبتأثر على الأداء سلباً. ابدأ بـ 3–5 وقيس.

متى لا تستخدم هذه الطريقة

القاعدة العملية: لو القائمة أقل من 50–100 عنصر، الـ virtualization مكسبه مش ملحوظ والتعقيد مش مستاهل. كمان متستخدمهوش لو محتاج كل المحتوى موجود في الـ DOM للطباعة، أو للبحث داخل الصفحة، أو للفهرسة في محركات البحث. وفي حالة الارتفاعات شديدة التغيّر بدون قياس دقيق، النتيجة ممكن تبقى أسوأ من غير virtualization.

المصادر

  • توثيق web.dev الرسمي من Google: Virtualize large lists with react-window — مصدر فكرة الـ windowing وعدد العناصر الظاهرة والـ overscanCount.
  • web.dev — Rendering performance — مصدر ميزانية الإطار (16.66ms) وعمل الـ main thread.
  • patterns.dev — List Virtualization — مصدر تعريف الـ windowing وفائدته على عدد عقد الـ DOM.
  • توثيق react-window الرسمي وقاعدة الـ 50–100 عنصر كحد للبدء في استخدام الـ windowing.

الخطوة التالية

افتح أبطأ قائمة عندك في التطبيق، وافتح تبويب Performance في DevTools واعمل record وانت بتعمل scroll. لو شفت Long Tasks فوق 50 مللي ثانية متكررة، استبدل القائمة بـ FixedSizeList بنفس الكود فوق وقيس تاني. لو الـ Long Tasks اختفت، التمرير اتحل.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة