almessadi.
العودة إلى الفهرس

يبدأ اهتزاز التخطيط عندما تتعارض قراءة وكتابة DOM مع بعضها البعض_

واجهات برمجة التطبيقات الهندسية مثل `getBoundingClientRect()` مفيدة، لكنها تصبح مكلفة عندما يجبر الكود على إعادة تخطيط جديدة بشكل متكرر في منتصف تحديثات الأنماط وDOM.

تاريخ النشر10 ديسمبر 2024
وقت القراءة9 min read

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

تسمى تلك النمط عادةً اهتزاز التخطيط.

نمط الخطأ

هذا هو الشكل المكلف:

for (const item of items) {
  item.style.width = "200px";
  const rect = item.getBoundingClientRect();
  item.style.height = `${rect.width}px`;
}

قد يجبر كل استدعاء لـ getBoundingClientRect() المتصفح على تنفيذ العمل المعلق للتخطيط قبل أن يتمكن من التجاوب. إذا كان هذا يجري أثناء التمرير أو تغيير الحجم أو الرسوم المتحركة، ستصبح واجهة المستخدم متقطعة بسرعة.

نمط أفضل

اجمع القراءات أولاً. اجمع الكتابات ثانياً:

const widths = items.map((item) => item.getBoundingClientRect().width);

items.forEach((item, index) => {
  item.style.width = "200px";
  item.style.height = `${widths[index]}px`;
});

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

متى تكون هذه المسألة مهمة

عادةً ما تشعر بها في:

  • معالجات التمرير
  • حلقات الرسوم المتحركة
  • التفاعلات بالسحب والإفلات
  • القوائم الكبيرة مع التلاعب المباشر في DOM

المتصفح سريع عندما تترك له حرية تجميع العمل. يصبح مكلفاً عندما تجبره على الإجابة عن أسئلة الهندسة مباشرة بعد كل كتابة.

إذا كان يجب تشغيل الكود أثناء الرسوم المتحركة أو التفاعل، فإن requestAnimationFrame هو غالباً المكان المناسب لجدولة أعمال DOM المجمع بحيث تحدث القراءات والكتبات في حدود إطار أكثر توقعاً.

المزيد من القراءة