كيف تبدأ سريعًا مع VUE3.0: أدخل
التوصيات ذات الصلة بالتعلم: البرنامج التعليمي لـ JavaScript
معالجات الأحداث يمكن أن تتفاعل في تطبيقات الويب الحديثة، فإن العديد من المطورين سيستخدمون عن طريق الخطأ عددًا كبيرًا منهم في الصفحة
؟في JavaScript، يرتبط عدد معالجات الأحداث على الصفحة ارتباطًا مباشرًا بالأداء العام للصفحة. هناك العديد من الأسباب، مثل①كل وظيفة عبارة عن كائن وتشغل مساحة من الذاكرة، وكلما زاد عدد الكائنات، كان الأداء أسوأ.② سيؤدي عدد زيارات DOM المطلوبة لمعالج حدث محدد أولاً إلى تأخير الكل تفاعل الصفحة.
لـ (let value of value) { ul.innerHTML += '<li>${value}</li>';}
هذا الرمز غير فعال لأنه يجب تعيين داخلي HTML مرة واحدة لكل تكرار، وليس ذلك فحسب، يجب قراءة داخلي HTML أولاً لكل حلقة، وهذا هو لنقول، إنnerHTML يحتاج إلى الوصول إليه مرتين في حلقة واحدة.
Let itemsHtml = "";for(let value of value){ itemsHtml += '<li>${value}</li>';}ul.innerHTML = itemsHtml;
بعد هذا التعديل، ستكون الكفاءة أعلى بكثير، ويمكن أيضًا تعيين قيمة لـInnerHTML :
ul.innerHTML = values.map(value => '<li>${value}</li>').join(' ');
الحل لعدد كبير جدًا من معالجات الأحداث هو استخدام تفويض الأحداث. يعمل تفويض الحدث على تعزيز فقاعات الأحداث، مما يسمح لك باستخدام معالج حدث واحد فقط لإدارة نوع واحد من الأحداث. على سبيل المثال، حدث النقر يصل إلى المستند. وهذا يعني أنه يمكنك تحديد معالج حدث عند النقر للصفحة بأكملها، بدلاً من تحديد معالجات أحداث منفصلة لكل عنصر قابل للنقر.
<ul id="myGirls"> <li id="girl1">بيبي دونغ</li> <li id="girl2">يون يون</li> <li id="girl3">Medusa</li></ul>
يحتوي هذا على ثلاثة عناصر قائمة يجب أن تؤدي إجراءً معينًا عند النقر عليها. الطريقة المعتادة هي تحديد ثلاثة معالجات للأحداث:
Let item1 = document.getElementById("girl1 ");let item2 = document.getElementById("girl2");let item3 = document.getElementById("girl3");item1.addEventListener("click",(event) => { console.log("أنا بيبي دونغ!");})item2.addEventListener("click",(event) => { console.log("أنا يونيون!");})item3.addEventListener("click",(event) => { console.log("أنا ميدوسا!");})
يوجد عدد كبير جدًا من الرموز المتطابقة والرمز قبيح جدًا.
باستخدام تفويض الحدث، ما عليك سوى إضافة معالج حدث إلى عقدة السلف المشتركة لعناصر متعددة ويمكنك حل القبح!
Let list = document.getElementById("myGirls");list.addEventListener("click",(event) => { دع الهدف = Event.target; التبديل (الهدف. معرف) { حالة "فتاة 1": console.log("أنا بيبي دونغ!"); استراحة؛ حالة "الفتاة 2": console.log("أنا يونيون!"); استراحة؛ حالة "فتاة 3": console.log("أنا ميدوسا!"); استراحة؛ }})
كائن المستند متاح في أي وقت، ويمكنك إضافة معالج حدث إليه في أي وقت (دون انتظار DOMContentLoaded أو تحميل الأحداث)، واستخدامه لمعالجة كافة الأحداث من نوع ما في الصفحة. وهذا يعني أنه طالما أن الصفحة تعرض عناصر قابلة للنقر، فإنها ستعمل دون تأخير.
توفير الوقت المستغرق في إعداد إجراءات أحداث الصفحة.
تقليل الذاكرة المطلوبة للصفحة بأكملها وتحسين الأداء العام.
من خلال تعيين معالجات الأحداث للعناصر، يتم إنشاء اتصال بين كود المتصفح وكود JavaScript المسؤول عن تفاعل الصفحة. كلما زاد عدد استئناف هذا الاتصال، أصبح أداء الصفحة أسوأ. بالإضافة إلى تقييد مثل هذه الاتصالات من خلال تفويض الأحداث، يجب إزالة معالجات الأحداث غير المستخدمة على الفور. يرجع الأداء الضعيف للعديد من تطبيقات الويب إلى بقاء معالجات الأحداث غير المفيدة في الذاكرة.
هناك سببان لهذه المشكلة:
مثل حذف العقد من خلال طريقة DOM إزالة الطفل () أو استبدال الطفل (). الأكثر شيوعًا هو استخدام InternalHTML لاستبدال جزء معين من الصفحة ككل. في هذا الوقت، إذا كان هناك معالج حدث على العنصر المحذوف بواسطة InternalHTML، فلن يتم تنظيفه بشكل طبيعي بواسطة برنامج جمع البيانات المهملة.
لذلك، إذا كنت تعلم أنه سيتم حذف عنصر ما، فيجب عليك حذف معالج الحدث الخاص به يدويًا، مثل btn.onclick = null;//删除事件处理程序
يمكن أن يساعد تفويض الحدث أيضًا في حل هذه المشكلة تم استبداله بـ insideHTML، ولا تقم بإضافة معالج حدث إلى العنصر، فقط قم بإضافته إلى عقدة ذات مستوى أعلى.
إذا لم يتم تنظيف معالجات الأحداث بعد إلغاء تحميل الصفحة، فستظل في الذاكرة. بعد ذلك، في كل مرة يقوم فيها المتصفح بتحميل الصفحة وإلغاء تحميلها (مثل الانتقال للأمام أو للخلف أو للتحديث)، يزداد عدد الكائنات المتبقية في الذاكرة نظرًا لعدم إعادة تدوير معالجات الأحداث.
بشكل عام، من الأفضل حذف كافة معالجات الأحداث في معالج الأحداث onunload قبل إلغاء تحميل الصفحة. يمكن أيضًا رؤية ميزة تفويض الأحداث في هذا الوقت نظرًا لوجود عدد قليل من معالجات الأحداث، فمن السهل تذكر المعالجات التي سيتم حذفها.
Let ps = document.getElementsByTagName("p");for(let i = 0;i<ps.length;++i){ دع p = document.createElement("p"); document.body.appendChild(p);}
Let ps = document.getElementsByTagName("p");for(let i = 0,len=ps.length;i<len;++i){ دع p = document.createElement("p"); document.body.appendChild(p);}
يحصل السطر الأول في التعبير ① على HTMLCollection الذي يحتوي على كافة عناصر <p>
في المستند. نظرًا لأن هذه المجموعة هي في الوقت الفعلي، في أي وقت تضيف فيه عنصر <p>
جديدًا إلى الصفحة، ثم تقوم بالاستعلام عن هذه المجموعة، سيكون هناك عنصر آخر. نظرًا لأن المتصفح لا يريد حفظ المجموعة في كل مرة يتم إنشاؤها فيها، فسوف يقوم بتحديث المجموعة في كل زيارة. ستقوم كل حلقة بتقييم i < ps.length
، وهو ما يعني استعلامًا للحصول على جميع عناصر <p>
. نظرًا لأنه تم إنشاء عنصر <p>
جديد وإضافته إلى المستند داخل نص الحلقة، فستتم أيضًا زيادة قيمة ps.length في كل مرة خلال الحلقة. نظرًا لأنه سيتم زيادة كلتا القيمتين، فلن يتساوى i أبدًا مع ps.length
، لذا فإن التعبير ① سوف يسبب حلقة لا نهائية.
في التعبير ②، تتم تهيئة المتغير len الذي يحمل طول المجموعة، لأن len يحتفظ بطول المجموعة في بداية الحلقة، ولن تنمو هذه القيمة ديناميكيًا مع زيادة المجموعة ( for循环中初始化变量处只会初始化一次
)، لذلك يمكن تجنب مشكلة الحلقة اللانهائية التي تظهر في التعبير ①.
إذا كنت لا تريد تهيئة متغير، فيمكنك أيضًا استخدام التكرار العكسي:
Let ps = document.getElementsByTagName("p");for(let i = ps.length-1;i>=0;--i ){ دع p = document.createElement("p"); document.body.appendChild(p);}
التوصيات ذات الصلة: برنامج JavaScript التعليمي
ما سبق هو فهم متعمق لقضايا الذاكرة والأداء في JavaScript لمزيد من المعلومات، يرجى الانتباه إلى المقالات الأخرى ذات الصلة على موقع PHP الصيني!