يُعلمك الخيار ResizeObserver
عند تغيير حجم عنصر.
قبل ResizeObserver
، كان عليك إرفاق مستمع إلى resize
الخاص بالمستند.
الحدث لتلقي إشعار بأي تغيير في أبعاد إطار العرض. في معالج الحدث، عليك بعد ذلك تحديد العناصر التي تأثّرت
بهذا التغيير واستدعاء روتين معيّن للتفاعل بشكل مناسب. إذا كنت بحاجة إلى
الأبعاد الجديدة لعنصر ما بعد تغيير الحجم، كان عليك استدعاء
getBoundingClientRect()
أو getComputedStyle()
، ما قد يؤدي إلى إنشاء تنسيق
إذا لم تعمد إلى تجميع كل القراءات وكل
يكتب.
ولم يشمل ذلك الحالات التي تغيّر فيها حجم العناصر بدون تغيير حجم النافذة
الرئيسية. على سبيل المثال، إلحاق أطفال جدد وتعيين
نمط display
للعنصر إلى none
، أو يمكن أن تغير إجراءات مشابهة حجم
عنصر ما أو أشقائه أو أسلافه.
هذا هو السبب في أن ResizeObserver
هو أساس مفيد. ويتفاعل مع التغييرات في
حجم أيّ من العناصر المرصودة، بغض النظر عن سبب التغيير.
ويتيح أيضًا الوصول إلى الحجم الجديد للعناصر المرصودة.
واجهة برمجة التطبيقات
تشترك جميع واجهات برمجة التطبيقات التي تحمل اللاحقة Observer
التي ذكرناها أعلاه في تصميم بسيط لواجهة برمجة التطبيقات. ولا يُستثنى من ذلك ResizeObserver
. تُنشئ عنصر ResizeObserver
وتمرير استدعاء إلى الدالة الإنشائية. يتمّ تمرير مصفوفة من عناصر
ResizeObserverEntry
إلى دالة ردّ الاتصال، وهي إدخال واحد لكلّ عنصر يتمّ رصده، والتي
تحتوي على السمات الجديدة للعنصر.
var ro = new ResizeObserver(entries => {
for (let entry of entries) {
const cr = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Element size: ${cr.width}px x ${cr.height}px`);
console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
}
});
// Observe one or multiple elements
ro.observe(someElement);
بعض التفاصيل
ما الذي يتم الإبلاغ عنه؟
بشكل عام، يُبلغ عنصر
ResizeObserverEntry
عن مربّع محتوى عنصر من خلال سمة تُسمى
contentRect
، والتي تُعرِض عنصرًا من نوع
DOMRectReadOnly
. مربّع المحتوى هو المربّع الذي يمكن وضع المحتوى فيه. وهو
مربّع الحدود مطروحًا منه الحشو.
تجدر الإشارة إلى أنّه على الرغم من أنّ السمة ResizeObserver
تُبلغ عن السمتَين
contentRect
والمساحة المتروكة، فإنه يشاهد contentRect
فقط.
لا تخلط بين contentRect
ومربّع الحدود للعنصر. إنّ مربع الحدود
، وفقًا لما أبلغ عنه getBoundingClientRect()
، هو المربع الذي يحتوي على
العنصر بأكمله وسلفه. وتُعد ملفات SVG استثناءً للقاعدة، حيث
سيُبلغ ResizeObserver
عن أبعاد مربّع الإحاطة.
اعتبارًا من الإصدار 84 من Chrome، يحتوي ResizeObserverEntry
على ثلاث خصائص جديدة لتقديم معلومات أكثر تفصيلاً. تعرض كل سمة من هذه السمات علامة ResizeObserverSize
يحتوي على السمة blockSize
والسمة inlineSize
. تتناول هذه
المعلومات العنصر الذي تم رصده في وقت استدعاء دالة ردّ الاتصال.
borderBoxSize
contentBoxSize
devicePixelContentBoxSize
تعرض كل هذه العناصر صفائف للقراءة فقط لأنّه من المرجّح أن تتمكّن في المستقبل من معالجة العناصر التي تحتوي على أجزاء متعددة، والتي تحدث في سيناريوهات الأعمدة المتعددة. في الوقت الحالي، ستتضمّن هذه الصفائف عنصرًا واحدًا فقط.
إنّ توافق هذه السمات مع المنصات محدود، ولكن Firefox يتوافق مع السمتَين الأوليتَين.
متى يتم الإبلاغ عن هذه الرسائل؟
تفرض المواصفة أن يعالج ResizeObserver
جميع أحداث تغيير الحجم
قبل الرسم وبعد التخطيط. يصبح هذا استدعاء ResizeObserver
مكانًا مثاليًا لإجراء تغييرات على تخطيط صفحتك. وبما أنّ ResizeObserver
تتم معالجة
العناصر بين التنسيق والرسم، سيؤدي ذلك إلى إبطال
التنسيق فقط، وليس الرسم.
فهمت
قد تتساءلون عمّا يحدث إذا غيّرتُ حجم لعبة
داخل رد الاتصال بـ ResizeObserver
؟ الإجابة هي: سوف تقوم
بمكالمة أخرى على الفور. لحسن الحظ، يحتوي ResizeObserver
على
آلية لتجنُّب حلقات الاستدعاء اللانهائية والاعتماديات الدورية. لن تتم معالجة التغييرات في الإطار نفسه إلا إذا كان العنصر الذي تم تغيير حجمه في مستويات أكثر عمقًا في شجرة DOM مقارنةً بالعنصر الأكثر سطحية الذي تمت معالجته في التعليق الداعم السابق.
وإلا، سيتم تأجيلها إلى الإطار التالي.
طلب الانضمام
أحد الإجراءات التي تتيح لك السمة ResizeObserver
تنفيذها هو تنفيذ كل عنصر.
والاستعلامات عن الوسائط. من خلال مراقبة العناصر، يمكنك تحديد
نقاط توقف التصميم وتغيير أنماط العنصر. في ما يلي
مثال، المربّع الثاني
تغيير نصف قطر حده وفقًا لعرضه.
const ro = new ResizeObserver(entries => {
for (let entry of entries) {
entry.target.style.borderRadius =
Math.max(0, 250 - entry.contentRect.width) + 'px';
}
});
// Only observe the second box
ro.observe(document.querySelector('.box:nth-child(2)'));
هناك مثال آخر مثير للاهتمام وهو نافذة المحادثة. المشكلة التي تنشأ في تخطيط محادثة نموذجي من أعلى إلى أسفل هو موضع التمرير. لتجنُّب إرباك المستخدم، من المفيد تثبيت النافذة في أسفل المحادثة حيث تظهر أحدث الرسائل. بالإضافة إلى ذلك، يمكن لأي نوع من التخطيط تغيير (التفكير في انتقال الهاتف من الوضع الأفقي إلى الوضع العمودي أو العكس) تحقق الشيء نفسه.
يسمح لك ResizeObserver
بكتابة رمز واحد يهتم بـ
كلا السيناريوهين. إنّ تغيير حجم النافذة هو حدث يمكن لـ ResizeObserver
الالتقاط حسب التعريف، ولكن استدعاء appendChild()
يؤدي أيضًا إلى تغيير حجم هذا العنصر
(ما لم يتم تعيين overflow: hidden
)، لأنها تحتاج إلى توفير مساحة للجدول الجديد
عناصر. مع أخذ ذلك في الاعتبار، يستغرق الأمر عددًا قليلاً جدًا من الأسطر لتحقيق
التأثير:
const ro = new ResizeObserver(entries => {
document.scrollingElement.scrollTop =
document.scrollingElement.scrollHeight;
});
// Observe the scrollingElement for when the window gets resized
ro.observe(document.scrollingElement);
// Observe the timeline to process new messages
ro.observe(timeline);
رائع، أليس كذلك؟
من هنا، يمكنني إضافة المزيد من الرموز البرمجية للتعامل مع الحالة التي ينقر فيها المستخدم على السهم المتّجه للأعلى ويريد أن يبقى السهم في هذه الرسالة عند تلقّي رسالة جديدة.
هناك حالة استخدام أخرى لأي نوع من العناصر المخصصة التي تؤدي تنسيقًا خاصًا بها.
حتى ResizeObserver
، لم تكن هناك طريقة موثوقة للحصول على إشعار عند تغيُّر
أبعادها حتى يمكن ترتيب عناصرها مرة أخرى.
تأثيرات "مدى استجابة الصفحة لتفاعلات المستخدم" (INP)
مدى استجابة الصفحة لتفاعلات المستخدم (INP) هو مقياس يقيس الاستجابة العامة للصفحة لتفاعلات المستخدم. إذا كان مقياس INP للصفحة ضمن الحدّ "الجيد"، أي 200 ملي ثانية أو أقل، يمكن القول إنّ الصفحة تستجيب بشكل موثوق لتفاعلات المستخدِم معها.
وفي حين أن مقدار الوقت الذي يستغرقه تشغيل عمليات استدعاء الحدث استجابةً أن يساهم تفاعل المستخدم بشكل كبير في إجمالي وقت الاستجابة للتفاعل فهذا ليس الجانب الوحيد من مدى استجابة الصفحة لتفاعلات المستخدم (INP). يأخذ مقياس INP أيضًا في الاعتبار مقدار الوقت الذي يستغرقه العرض التالي للتفاعل. هذه هي مقدار الوقت المستغرق في عملية العرض اللازمة لتعديل بيانات المستخدم واجهة المستخدم استجابة لتفاعل لإكماله.
في ما يتعلّق بـ ResizeObserver
، هذا مهم لأنّ دالة الاستدعاء التي
تُنفّذ مثيل ResizerObserver
تحدث قبل بدء عملية التقديم مباشرةً. هذا النمط
عن طريق الخطأ، حيث يجب أخذ العمل الذي يحدث في معاودة الاتصال
فمن المرجح أن يتطلب هذا العمل تغييرًا في
واجهة المستخدم.
احرص على تنفيذ أقل قدر ممكن من عمليات المعالجة المطلوبة في ResizeObserver
الاستدعاء، لأنّ عمليات المعالجة المفرطة يمكن أن تؤدي إلى حدوث حالات يتأخّر فيها المتصفّح عن تنفيذ مهام مهمة. على سبيل المثال، إذا كان أي تفاعل له
تؤدي إلى تنفيذ معاودة الاتصال بالرمز ResizeObserver
، تأكَّد من تنفيذ
التالية لتسهيل الحصول على أفضل تجربة ممكنة:
- تأكَّد من أنّ أدوات اختيار لغة CSS بسيطة قدر الإمكان لتجنّبها عملية إعادة احتساب النمط بشكل مفرط. تحدث عمليات إعادة احتساب الأنماط قبل التنسيق مباشرةً، ويمكن أن تؤدّي أدوات اختيار لغة CSS المعقّدة إلى تأخير عمليات التنسيق.
- تجنُّب تنفيذ أي عمل يمكن أن يؤدي إلى استدعاء ميزة "
ResizeObserver
" عمليات إعادة التدفق الإلزامية: - يزداد الوقت اللازم لتحديث تنسيق الصفحة بشكل عام مع
عدد عناصر DOM في الصفحة. وعلى الرغم من أن ذلك يكون صحيحًا سواء كانت الصفحات تستخدم
ResizeObserver
، يمكن أن يصبح العمل المنجز في معاودة الاتصال على "ResizeObserver
" أهمية مع زيادة التعقيد الهيكلي للصفحة.
الخاتمة
يتوفّر ResizeObserver
في جميع المتصفّحات
الكبرى
ويوفّر طريقة فعّالة لرصد عمليات تغيير حجم العناصر على مستوى
العنصر. فقط احرِص على عدم تأخير العرض كثيرًا باستخدام واجهة برمجة التطبيقات هذه القوية.