تنويهيبدو أنني بدأت سلسلة جديدة من المقالات - مملّة قليلاً ومفيدة تمامًا. سيشرحون النقاط التي غالبًا ما تسبب صعوبات لطلابي. إذا كنت مطور ويب متمرس ، فعلى الأرجح لن تكون مهتمًا. إذا كنت تنتظر الانحرافات في قوة شبيبة الجمعة ، فلن يكونوا هنا ، للأسف.
يعد DocumentFragment أحد الأشياء التي يواجه الطلاب صعوبة في فهمها بانتظام. بشكل عام ، لا يمكنني إلقاء اللوم عليهم. مع البساطة الخارجية ، لديها العديد من الخصائص غير الواضحة وحتى المضادة للحدس. في هذه المقالة ، أريد جمع كل ما يحتاج المبتدئ إلى معرفته عنه.

ما هذا
إن DocumentFragment عبارة عن حاوية يمكن أن تحتوي على عدد عشوائي من عناصر DOM. إذا كان الأمر ببساطة ، يمكنك تخيله كدلو. يتم تكديس العناصر فيه بحيث يمكن التخلص منها في الوقت المناسب فورًا.
كيف تصنع
ابتدائي.
var fragment = document.createDocumentFragment();
هناك أيضًا طرق أخرى ، ولكن حولها أدناه.
لماذا أحتاج
كما كتبت أعلاه ، من أجل تخزين عناصر DOM. قد يعترض القارئ "لكن يمكن تخزينها في مغنية عادية". صحيح أن الجزء له خاصية فريدة تجعله المرشح الأفضل لهذا الدور. خذ بعين الاعتبار الرمز التالي:
var fragment = document.createDocumentFragment(); var parentDiv = document.createElement("div"); var div1 = document.createElement("div"); var div2 = document.createElement("div"); fragment.appendChild(div1); fragment.appendChild(div2);
ماذا ستخبرنا وحدة التحكم؟ قد يظن شخص غير معتاد على DocumentFragment أن
parentDiv
سيكون لديه طفل واحد -
fragment
. ولكن في الواقع ، سيكون لديها طفلان -
div1
و
div2
. والحقيقة هي أن الجزء نفسه ليس عنصر DOM ، إنه مجرد حاوية لعناصر DOM. وعندما يتم تمريره كحجة لطرق مثل
appendChild
أو
insertBefore
، فإنه لا يتم تضمينه في شجرة DOM ، بل يقوم بدمج محتوياته هناك.
لكن لماذا تحتاجها؟
إن خاصية "الدلو" جيدة بالطبع ، ولكن ما مدى فائدة ذلك عمليًا؟ يحتوي DocumentFragment على مجالين رئيسيين للتطبيق.
1. تخزين أجزاء HTML التي ليس لها سلف مشترك.هناك حالات نحتاج فيها إلى استبدال محتويات عنصر ، ولكن لا تلمس العنصر نفسه. افترض أننا نستخدم تفويض الحدث ، وأن جميع معالجات الأحداث التي تحدث على العناصر الداخلية معلقة على قسم خارجي. في هذه الحالة ، يعد DocumentFragment مثاليًا لنا:
div.innerHTML = ""; div.appendChild(fragmentWithAllContent);
"ولكن هل يمكننا فقط إضافة عناصر إلى div فور إنشائها؟" - يسأل القارئ التآكل. نستطيع ، لكن الأمر لا يستحق ، ولهذا السبب.
2. تحسين الأداء في حالة الإدخالات المتعددة.والحقيقة هي أنه في كل مرة نغير فيها شيئًا في شجرة DOM النشطة ، يجب على المتصفح إجراء مجموعة من الحسابات. يمكنك قراءة المزيد عن هذا
هنا ، على سبيل المثال. في هذه المقالة ، نقصر أنفسنا على الإشارة إلى أن هناك مثل هذا الوحش الرهيب - التدفق. عندما نضيف عنصرًا إلى الصفحة ، يستيقظ هذا الوحش ويأكل جزءًا من وقت المعالج. إذا أضفنا مائة عنصر بدوره ، سيستيقظ الوحش مائة مرة ويصنع لدغة مائة مرة. بالنسبة للمستخدم ، قد يكون هذا "تجميد" ملحوظًا بالفعل.
عندما نضيف عنصرًا إلى DocumentFragment ، فإن هذا لا يسبب إعادة التدفق ، لأن الجزء ليس جزءًا (ولا يمكن أن يكون في الأساس) جزءًا من شجرة DOM النشطة. والأهم من ذلك: عندما ندرج محتويات جزء باستخدام
appendChild
أو طرق أخرى مماثلة ، بغض النظر عن عدد العناصر الموجودة داخل الجزء ،
يتم استدعاء إعادة التدفق مرة واحدة فقط .
من أجل الوضوح ، قمت بعمل مقياس
بسيط بحيث يمكن للقارئ أن يرى الفرق شخصيًا.
تحديث:
قال الرفيق
نويت أن كلماتي لم تعد صحيحة بالنسبة إلى Chrome الحديث. في ذلك ، لا يتم تنفيذ إعادة التدفق في وقت أبكر من اللازم ، وبفضل هذا ، يعمل الرمز بدون DocumentFragment في الواقع بشكل
أسرع ، ومع المتصفحات الأخرى ليس واضحًا جدًا. لذلك قبل أن تقرر ما إذا كنت تريد استخدام الأجزاء ، فأنت بحاجة إلى التنميط والبحث على الجمهور المستهدف للموقع.
الفروق الدقيقة
هناك ميزتان تجعل المبتدئين غالبًا ما يصعب عليهم استخدام الأجزاء. أولاً: كما كتبت أعلاه ، الجزء
ليس عنصر DOM . هذا يعني أنها تفتقر إلى العديد من الأساليب والخصائص المألوفة ، على وجه الخصوص -
innerHTML
. لذلك ، لا يمكنك فقط تحويل سلسلة إلى محتويات جزء. كيفية القيام بذلك ليس سهلاً ، سيتم شرحه أدناه.
السمة الثانية: الجزء عند استخدام "الغنائم". بتعبير أدق ، يتم تفريغه. عندما نفعل
div.appendChild(fragment)
، يتم
div.appendChild(fragment)
جميع أطفال الجزء في
div
. وبما أن العنصر لا يمكن أن يحتوي على أكثر من أحد الوالدين ، فهذا يعني أنه تمت إزالته من الجزء! لتجنب هذا السلوك عندما يكون غير مرغوب فيه ، يمكنك استخدام
cloneNode
.
علامة <template>
هناك مكان واحد حيث يمكنك العثور على DocumentFragment دون إنشائه من خلال JS. هذه هي خاصية
content
لعنصر القالب.
<template>
ابتكار
<template>
خصيصًا لتخزين أجزاء من كود HTML ، ولكن ليس لتحميل المتصفح مسبقًا. لا يصبح ما بداخل هذه العلامة جزءًا من شجرة DOM النشطة. على وجه الخصوص (غالبًا ما
querySelector
القادمون الجدد هذا أيضًا) ، ولا يمكن العثور
querySelector
باستخدام
querySelector
. لا تصبح العناصر التي تم إنشاؤها من كود HTML داخل علامة
<template>
تابعة لها. بدلاً من ذلك ، يمكن لـ JavaScript الوصول إليها من خلال خاصية
content
، وهي - مفاجأة! - فقط DocumentFragment.
باستخدام عنصر القالب ، يمكنك إنشاء جزء من سلسلة:
function createFragmentFromString(str){ var template = document.createElement("template"); template.innerHTML = str; return template.content; }
الخاتمة
إذا كنت جديدًا في تطوير الويب ، آمل أن تكون قد تعلمت الكثير. إذا كنت مطورًا ذا خبرة ، فقد ترغب في استكمال هذه المقالة بشيء ، وفي هذه الحالة لا تتردد في الكتابة عنها في التعليقات. شكرا للقراءة ، ونتمنى لك يوما سعيدا.