شرح أحداث JavaScript

يستخدم JavaScript في المستعرض نموذج برمجة يعتمد على الأحداث. كل شيء يبدأ باتباع حدث. هذه مقدمة لأحداث JavaScript وكيفية عمل معالجة الأحداث

مقدمة

يستخدم JavaScript في المستعرض نموذج برمجة يعتمد على الأحداث.

كل شيء يبدأ باتباع حدث.

يمكن أن يكون الحدث هو تحميل DOM ، أو طلب غير متزامن ينتهي من الجلب ، أو نقر المستخدم على عنصر أو تمرير الصفحة ، أو يكتب المستخدم على لوحة المفاتيح.

هناك الكثير من أنواع الأحداث المختلفة.

معالجات الأحداث

يمكنك الرد على أي حدث باستخداممعالج الحدث، وهي وظيفة يتم استدعاؤها عند وقوع حدث ما.

يمكنك تسجيل معالجات متعددة لنفس الحدث ، وسيتم استدعاؤها جميعًا عند حدوث هذا الحدث.

تقدم JavaScript ثلاث طرق لتسجيل معالج الأحداث:

معالجات الأحداث المضمنة

نادرًا ما يتم استخدام هذا النمط من معالجات الأحداث اليوم ، نظرًا لقيوده ، ولكنه كان الطريقة الوحيدة في أيام JavaScript الأولى:

<a href="site.com" onclick="dosomething();">A link</a>

معالجات DOM عند الحدث

هذا شائع عندما يكون للكائن معالج حدث واحد على الأكثر ، حيث لا توجد طريقة لإضافة معالجات متعددة في هذه الحالة:

window.onload = () => {
  //window loaded
}

يستخدم بشكل شائع عند المناولةXHRالطلبات:

const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
  //.. do something
}

يمكنك التحقق مما إذا تم تعيين معالج بالفعل لخاصية باستخدامif ('onsomething' in window) {}.

استخدامaddEventListener()

هذا البالطريقة الحديثة. تسمح هذه الطريقة بتسجيل أكبر عدد من المعالجات التي نحتاجها ، وهي الطريقة الأكثر شيوعًا التي ستجدها:

window.addEventListener('load', () => {
  //window loaded
})

لاحظ أن IE8 والإصدارات الأقدم لم تدعم هذا ، وبدلاً من ذلك استخدمهاattachEvent()API. ضع في اعتبارك إذا كنت بحاجة إلى دعم المتصفحات القديمة.

الاستماع إلى عناصر مختلفة

يمكنك الاستماعwindowلاعتراض الأحداث "العالمية" ، مثل استخدام لوحة المفاتيح ، ويمكنك الاستماع إلى عناصر محددة للتحقق من الأحداث التي تحدث عليها ، مثل النقر بالماوس على زر.

هذا هو السببaddEventListenerأحيانًا ما يتم استدعاؤهwindow، أحيانًا على عنصر DOM.

كائن الحدث

يحصل معالج الحدث على ملحقEventالكائن كمعامل أول:

const link = document.getElementById('my-link')
link.addEventListener('click', event => {
  // link clicked
})

يحتوي هذا الكائن على الكثير من الخصائص والطرق المفيدة ، مثل:

  • target، عنصر DOM الذي أنشأ الحدث
  • type، نوع الحدث
  • stopPropagation()دعا لوقف نشر الحدث في DOM

(انظر القائمة الكاملة).

يتم توفير الخصائص الأخرى حسب نوع معين من الأحداث ، مثلEventهي واجهة لأحداث محددة مختلفة:

كل من هؤلاء لديهم صفحة MDN مرتبطة ، حتى تتمكن من فحص جميع خصائصهم.

على سبيل المثال ، عند حدوث حدث لوحة المفاتيح ، يمكنك التحقق من المفتاح الذي تم الضغط عليه ، بتنسيق يمكن قراءته (EscapeوEnterوهلم جرا) عن طريق التحقق منkeyمنشأه:

window.addEventListener('keydown', event => {
  // key pressed
  console.log(event.key)
})

في حدث الماوس ، يمكننا التحقق من زر الماوس الذي تم الضغط عليه:

const link = document.getElementById('my-link')
link.addEventListener('mousedown', event => {
  // mouse button pressed
  console.log(event.button) //0=left, 2=right
})

فقاعات الحدث والتقاط الحدث

الفقاعات والتقاط هما النموذجان اللذان تستخدمهما الأحداث للتكاثر.

افترض أن هيكل DOM الخاص بك هو

<div id="container">
  <button>Click me</button>
</div>

تريد تتبع الوقت الذي ينقر فيه المستخدمون على الزر ، ولديك مستمعان للحدث ، واحد علىbutton، وواحد في#container. تذكر أن النقر على عنصر فرعي سينتشر دائمًا إلى والديه ، إلا إذا أوقفت النشر (انظر لاحقًا).

سيتم استدعاء مستمعي الأحداث هؤلاء بالترتيب ، ويتم تحديد هذا الترتيب من خلال نموذج الفقاعة / الالتقاط المستخدم.

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

في مثالنا ، المعالج يعملbuttonسوف يطلق النار قبل#containerمعالج.

اسرهو عكس ذلك: يتم تشغيل معالجات الأحداث الخارجية قبل المعالج الأكثر تحديدًا ، والمعالج الموجودbutton.

افتراضيا جميع الأحداث فقاعة.

يمكنك اختيار اعتماد التقاط الحدث من خلال تطبيق وسيطة ثالثة على addEventListener ، وتعيينها علىtrue:

document.getElementById('container').addEventListener(
  'click',
  () => {
    //window loaded
  },
  true
)

لاحظ أنأولًا ، يتم تشغيل جميع معالجات أحداث الالتقاط.

ثم كل معالجات الأحداث الفقاعية.

يتبع الترتيب هذا المبدأ: يمر DOM عبر جميع العناصر بدءًا من كائن Window ، ويذهب للعثور على العنصر الذي تم النقر عليه. أثناء القيام بذلك ، فإنه يستدعي أي معالج حدث مرتبط بالحدث (مرحلة الالتقاط).

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

وقف التكاثر

سيتم نشر حدث في عنصر DOM إلى كل شجرة عناصره الأصلية ، ما لم يتم إيقافه.

<html>
  <body>
    <section>
      <a id="my-link" ...>

انقر فوق الحدثaسوف تنتشر إلىsectionوثمbody.

يمكنك إيقاف التكاثر باستدعاءstopPropagation()طريقة حدث ، عادةً في نهاية معالج الحدث:

const link = document.getElementById('my-link')
link.addEventListener('mousedown', event => {
  // process the event
  // ...

  event.stopPropagation()
})

فيما يلي قائمة بالأحداث الأكثر شيوعًا التي من المحتمل أن تتعامل معها.

حمل

loadأطلق عليهwindowو الbodyالعنصر عند انتهاء تحميل الصفحة.

أحداث الماوس

clickحرائق عند النقر فوق زر الماوس.dblclickعندما يتم النقر بالماوس مرتين. بالطبع في هذه الحالةclickتم إطلاقه قبل هذا الحدث مباشرة.mousedownوmousemoveوmouseupيمكن استخدامها معًا لتتبع أحداث السحب والإفلات. كن حذرا معmousemove، حيث يتم إطلاقه عدة مرات أثناء حركة الماوس (انظرخانقفي وقت لاحق)

أحداث لوحة المفاتيح

keydownحرائق عند الضغط على زر لوحة المفاتيح (وفي أي وقت يتكرر المفتاح أثناء الزريبقىضغط).keyupعند تحرير المفتاح.

انتقل

الscrollتم تشغيل الحدثwindowفي كل مرة تقوم فيها بالتمرير في الصفحة. داخل معالج الأحداث ، يمكنك التحقق من موضع التمرير الحالي عن طريق التحققwindow.scrollY.

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

خانق

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

هذا لأنها توفر إحداثيات حتى تتمكن من تتبع ما يحدث.

إذا قمت بإجراء عملية معقدة في معالج الحدث ، فسوف تؤثر على الأداء وتسبب تجربة بطيئة لمستخدمي موقعك.

المكتبات التي توفر الاختناق مثللوداشتطبيقه في أكثر من 100 سطر من التعليمات البرمجية للتعامل مع كل حالة استخدام ممكنة. تطبيق بسيط وسهل الفهم هو هذا الذي يستخدمsetTimeoutللتخزين المؤقت لحدث التمرير كل 100 مللي ثانية:

let cached = null
window.addEventListener('scroll', event => {
  if (!cached) {
    setTimeout(() => {
      //you can access the original event at `cached`
      cached = null
    }, 100)
  }
  cached = event
})

المزيد من دروس js: