Γειά σου! Σε αυτό το μάθημα, θέλω να μιλήσω για μια τόσο σημαντική έννοια όπως η φυσαλίδα και η αναχαίτιση γεγονότων. Το Bubbling είναι ένα φαινόμενο κατά το οποίο εάν κάνετε κλικ σε ένα θυγατρικό στοιχείο, το συμβάν μεταδίδεται στον γονέα του.

Μπορεί να είναι πολύ χρήσιμο κατά την επεξεργασία μεγάλων ένθετων λιστών ή πινάκων, για να μην εκχωρήσετε έναν χειριστή συμβάντων σε κάθε στοιχείο, μπορείτε να εκχωρήσετε έναν χειριστή ανά γονικό στοιχείο, και το συμβάν θα μεταδοθεί ήδη σε όλα τα ένθετα στοιχεία του γονέα. Ας δούμε ένα παράδειγμα.

Αυτός ο χειριστής είναι για

θα λειτουργήσει εάν κάνετε κλικ σε μια ένθετη ετικέτα ή :

Κάντε κλικ στο EM, ο χειριστής στο DIV θα λειτουργήσει

Όπως μπορείτε να δείτε, όταν κάνετε κλικ στο ένθετο στοιχείο em, ενεργοποιείται ο χειριστής στο div. Γιατί συμβαίνει αυτό? Διαβάστε παρακάτω και μάθετε.

Ανάβαση

Η βασική αρχή της ανάβασης λοιπόν:

Για οποιοδήποτε συμβάν, δεν έχει σημασία αν το ποντίκι κάνει κλικ στο στοιχείο, το συμβάν θα λειτουργήσει πρώτα στο γονικό στοιχείο και, στη συνέχεια, κατά μήκος της αλυσίδας θα εξαπλωθεί σε όλα τα ένθετα στοιχεία.

Για παράδειγμα, ας υποθέσουμε ότι υπάρχουν 3 ένθετα στοιχεία FORM > DIV > P, με έναν χειριστή συμβάντων σε καθένα:

ΜΟΡΦΗ
DIV

Η δημιουργία φυσαλίδων διασφαλίζει ότι γίνεται κλικ στο εσωτερικό στοιχείο

Θα καλέσει το πρόγραμμα χειρισμού κλικ (εάν υπάρχει) πρώτα στο

Μια τέτοια διαδικασία ονομάζεται φυσαλίδες, επειδή τα γεγονότα, σαν να λέγαμε, «επιπλέουν» από το εσωτερικό στοιχείο προς τα πάνω μέσω των γονιών τους, όπως μια φυσαλίδα αέρα επιπλέει στο νερό, έτσι μπορείτε επίσης να βρείτε τον ορισμό της φυσαλίδας, λοιπόν, είναι απλώς από την αγγλική λέξη bubbling - επιπλέω.

Πρόσβαση στο στοιχείο προορισμού event.target

Για να μάθουμε σε ποιο στοιχείο πιάσαμε αυτό ή εκείνο το συμβάν, υπάρχει η μέθοδος event.target. (διαβάστε για το αντικείμενο συμβάντος).

  • συμβάν.στόχος- αυτό είναι το ίδιο το αρχικό στοιχείο, στο οποίο συνέβη το συμβάν.
  • Αυτό- αυτό είναι πάντα το τρέχον στοιχείο στο οποίο έφτασε η φυσαλίδα και ο χειριστής εκτελεί αυτήν τη στιγμή σε αυτό.

Για παράδειγμα, εάν έχετε εγκαταστήσει μόνο ένα πρόγραμμα χειρισμού form.onclick, τότε θα "πιάσει" όλα τα κλικ μέσα στη φόρμα. Ταυτόχρονα, όπου υπάρχει ένα κλικ μέσα, θα εξακολουθεί να εμφανίζεται στο στοιχείο

, στο οποίο θα εργαστεί ο χειριστής.

Εν:

  • Αυτό(=event.currentTarget) θα είναι πάντα η ίδια η φόρμα, αφού ο χειριστής εργάστηκε σε αυτήν.
  • συμβάν.στόχοςθα περιέχει έναν σύνδεσμο προς ένα συγκεκριμένο στοιχείο μέσα στη φόρμα, το πιο ένθετο, στο οποίο έγινε το κλικ.

Κατ 'αρχήν, αυτό μπορεί να είναι το ίδιο με το event.target εάν γίνει κλικ στη φόρμα και δεν υπάρχουν άλλα στοιχεία στη φόρμα.

Διακοπή ανάβασης

Συνήθως, η φυσαλίδα συμβάντος πηγαίνει κατευθείαν στην κορυφή και φτάνει στο αντικείμενο του παραθύρου ρίζας.

Είναι όμως δυνατό να σταματήσει η ανάβαση σε κάποιο ενδιάμεσο στοιχείο.

Για να σταματήσετε τη δημιουργία φυσαλίδων, καλέστε τη μέθοδο event.stopPropagation().

Ας δούμε ένα παράδειγμα όπου ο χειριστής body.onclick δεν θα λειτουργεί όταν κάνετε κλικ στο κουμπί:

Εάν το στοιχείο έχει πολλούς χειριστές για το ίδιο συμβάν, τότε ακόμα κι αν σταματήσει η φυσαλίδα, θα εκτελεστούν όλοι.

Έτσι, το stopPropagation θα αποτρέψει την περαιτέρω διάδοση του συμβάντος, αλλά όλοι οι χειριστές θα εργαστούν στο στοιχείο, αλλά όχι περαιτέρω στο επόμενο στοιχείο.

Για να σταματήσει η επεξεργασία του τρέχοντος στοιχείου, τα προγράμματα περιήγησης υποστηρίζουν τη μέθοδο event.stopImmediatePropagation(). Αυτή η μέθοδος όχι μόνο θα αποτρέψει τη δημιουργία φυσαλίδων, αλλά και θα σταματήσει την επεξεργασία συμβάντων στο τρέχον στοιχείο.

Βύθιση

Στο πρότυπο, εκτός από την «ανάδυση» των γεγονότων, υπάρχει και μια «βύθιση».

Οι καταδύσεις, σε αντίθεση με την ανάβαση, έχουν λιγότερη ζήτηση, αλλά θα είναι ακόμα χρήσιμο να το γνωρίζουμε.

Έτσι, υπάρχουν 3 στάδια του πάσου εκδήλωσης:

  1. Η εκδήλωση πηγαίνει από πάνω προς τα κάτω. Αυτό το στάδιο ονομάζεται «στάδιο αναχαίτισης».
  2. Το γεγονός έφτασε σε ένα συγκεκριμένο στοιχείο. Αυτό είναι το στάδιο του στόχου.
  3. Μετά από όλα, το συμβάν αρχίζει να αναδύεται. Αυτό είναι το «πλωτό στάδιο».

Αυτό φαίνεται στο πρότυπο ως εξής:

Έτσι, όταν κάνετε κλικ σε ένα TD, το συμβάν θα ταξιδέψει μέσω της αλυσίδας των γονέων, πρώτα προς τα κάτω στο στοιχείο ("βυθίσεις") και στη συνέχεια προς τα πάνω ("επιπλέει"), ενεργοποιώντας αντίστοιχα τους χειριστές στην πορεία.

Παραπάνω έγραψα μόνο για την ανάβαση, γιατί τα άλλα στάδια από μόνα τους δεν χρησιμοποιούνται και περνούν απαρατήρητα από εμάς.

Οι χειριστές δεν ξέρουν τίποτα για το στάδιο της αναχαίτισης, αλλά αρχίζουν να εργάζονται από τη φυσαλίδα.

Και για να παρακολουθήσετε ένα συμβάν στο στάδιο της υποκλοπής, πρέπει απλώς να χρησιμοποιήσετε:

  • Το επιχείρημα είναι αληθές, τότε το συμβάν θα υποκλαπεί κατά την οδό προς τα κάτω.
  • Το όρισμα είναι ψευδές, τότε το συμβάν θα καταγραφεί κατά τη δημιουργία φυσαλίδων.

Παραδείγματα

Στο παράδειγμα στο ,

,

Υπάρχουν οι ίδιοι χειριστές όπως πριν, αλλά αυτή τη φορά - στο στάδιο της βύθισης. Λοιπόν, για να δείτε την υποκλοπή σε δράση, κάντε κλικ στο στοιχείο σε αυτό

Οι χειριστές θα λειτουργούν με σειρά από πάνω προς τα κάτω: FORM → DIV → P.

Ο κώδικας JS έχει ως εξής:

varelems = document.querySelectorAll("form,div,p"); // σε κάθε στοιχείο θα κρεμάσουμε έναν χειριστή στο στάδιο της υποκλοπής για (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); }


Κανείς δεν σας ενοχλεί να ορίσετε χειριστές και για τα δύο στάδια, όπως αυτό:

varelems = document.querySelectorAll("form,div,p"); για (var i = 0; i< elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); elems[i].addEventListener("click", highlightThis, false); }

Κάντε κλικ στο εσωτερικό στοιχείο

Για να δείτε τη σειρά με την οποία μεταβιβάζεται ένα συμβάν:
Θα πρέπει να είναι FORM → DIV → P → P → DIV → FORM. Σημειώστε ότι το στοιχείο

Θα συμμετάσχει και στα δύο στάδια.

Αποτελέσματα

  • Όταν συμβαίνει ένα συμβάν, το στοιχείο στο οποίο συνέβη το συμβάν επισημαίνεται ως event.target.
  • Το συμβάν κατευθύνεται αρχικά από τη ρίζα του εγγράφου στο event.target, καλώντας τους χειριστές που παρέχονται μέσω του addEventListener(…., true) στην πορεία.
  • Το συμβάν ταξιδεύει από το event.target μέχρι την αρχή του εγγράφου, στην πορεία καλεί τους χειριστές που παρέχονται μέσω του addEventListener(…., false).

Κάθε χειριστής θα έχει πρόσβαση στις ιδιότητες του συμβάντος:

  • Το event.target είναι το βαθύτερο στοιχείο στο οποίο πραγματικά συνέβη το συμβάν.
  • event.currentTarget (=αυτό) είναι το στοιχείο στο οποίο το αυτή τη στιγμήο αυτοεξυπηρετούμενος δούλεψε (στο οποίο «έφθασε» το γεγονός).
  • event.eventPhase - σε ποια φάση ενεργοποίησε ο χειριστής συμβάντων (dive = 1, float = 3).

Η δημιουργία φυσαλίδων μπορεί να σταματήσει καλώντας τη μέθοδο event.stopPropagation(), αλλά αυτό δεν συνιστάται καθώς μπορεί να χρειαστείτε το συμβάν για απροσδόκητους σκοπούς.

Τώρα θα ρίξουμε μια ματιά σε ορισμένα προηγμένα πράγματα κατά την εργασία με το αντικείμενο Event, συγκεκριμένα: φυσαλίδες και υποκλοπές, καθώς και ανάθεση συμβάντων.

Φούσκα εκδήλωσης

Φανταστείτε ότι έχετε πολλά ένθετα μπλοκ:

το πιο εσωτερικό μπλοκ

Όταν κάνετε κλικ στο πιο εσωτερικό μπλοκ, το συμβάν στο κλικεμφανίζεται πρώτα σε αυτό, και μετά πυροδοτείται στον γονέα του, στον γονέα του γονέα του και ούτω καθεξής, μέχρι να φτάσει σε αυτήν την ετικέτα σώμακαι στην ετικέτα html(μετά να έγγραφοκαι πριν παράθυρο).

Και αυτό είναι λογικό, γιατί κάνοντας κλικ στο εσωτερικό μπλοκ, κάνετε ταυτόχρονα κλικ σε όλα τα εξωτερικά.

Ας το δούμε αυτό στο ακόλουθο παράδειγμα: έχουμε 3 μπλοκ, καθένα από αυτά έχει ένα συμβάν onclick συνδεδεμένο σε αυτό:

Κάντε κλικ στο πιο εσωτερικό κόκκινο μπλοκ - και θα δείτε πώς θα λειτουργήσει πρώτα το onclick του κόκκινου μπλοκ, μετά το μπλε και μετά το πράσινο:

Αυτή η συμπεριφορά ονομάζεται επιφανειακάγεγονότα - κατ' αναλογία με την ανάβαση μιας φυσαλίδας αέρα από τον πυθμένα. Ακριβώς όπως η φούσκα, το κλικ μας στο εσωτερικό στοιχείο φαίνεται να επιπλέει στην κορυφή, κάθε φορά που ενεργοποιείται σε υψηλότερα μπλοκ.

συμβάν.στόχος

Ας υποθέσουμε ότι έχουμε δύο στοιχεία: ένα div και μια παράγραφο p που βρίσκεται μέσα σε αυτό το div. Ας δέσουμε τον onlick σε μια ντίβα:

Όταν κάνουμε κλικ σε αυτό το div, μπορούμε να πάμε σε μια παράγραφο ή μπορούμε να πάμε σε ένα μέρος όπου αυτή η παράγραφος δεν υπάρχει.

Πώς μπορεί να συμβεί αυτό - δείτε το ακόλουθο παράδειγμα: το πράσινο είναι το div μας και το μπλε είναι η παράγραφός μας:

Εάν κάνετε κλικ στο πράσινο μέρος, θα κάνουμε κλικ στο div, και εάν κάνετε κλικ στο μπλε μέρος, το κλικ θα γίνει πρώτα στην παράγραφο και μετά στο div. Αλλά επειδή το onclick είναι συνδεδεμένο ειδικά στο div, γενικά μπορεί να μην παρατηρήσουμε την παρουσία της παραγράφου.

Ωστόσο, μερικές φορές θα θέλαμε να μάθουμε αν το κλικ συνέβη απευθείας στο div ή στην απόγονη παράγραφο του. Το αντικείμενο Event και η ιδιότητά του θα μας βοηθήσουν σε αυτό. συμβάν.στόχος- αποθηκεύει ακριβώς το στοιχείο στο οποίο έγινε το κλικ.

Στο παρακάτω παράδειγμα, έχουμε div, μέσα του βρίσκεται Πκαι μέσα σε αυτό - σπιθαμή.

Ας συνδέσουμε το συμβάν onclick στο ανώτατο στοιχείο (div) και κάνουμε κλικ σε διαφορετικά στοιχεία: div, p, span. Με τη χρήση συμβάν.στόχοςλάβετε το πιο κάτω στοιχείο όπου συνέβη το συμβάν και εμφανίστε το όνομά του χρησιμοποιώντας το tagName .

Εάν κάνετε κλικ, για παράδειγμα, στο διάστημα, τότε το συμβάν θα πιάσει το div μας (εξάλλου, το onclick είναι συνδεδεμένο σε αυτό), αλλά σε συμβάν.στόχοςθα πει ψέματα ακριβώς σπιθαμή:

Κάντε κλικ σε διαφορετικά μπλοκ - θα δείτε το αποτέλεσμα:

Διακοπή ανάβασης

Έτσι, γνωρίζετε ήδη ότι όλα τα συμβάντα εμφανίζονται στην κορυφή (μέχρι ετικέτα htmlκαι μετά στο τεκμηρίωση και μετά στο παράθυρο). Μερικές φορές υπάρχει ανάγκη να σταματήσει αυτή η ανάβαση. Αυτό μπορεί να γίνει από οποιοδήποτε στοιχείο μέσω του οποίου εμφανίζεται το συμβάν. Για να το κάνετε αυτό, στον κωδικό στοιχείου, καλέστε τη μέθοδο event.stopPropagation().

Στο παρακάτω παράδειγμα, κάνοντας κλικ στο κόκκινο μπλοκ θα λειτουργήσει μόνο του, μετά στο μπλε μπλοκ και τέλος - το μπλε μπλοκ σταματά την περαιτέρω ανάβαση και το πράσινο μπλοκ δεν θα αντιδράσει με κανέναν τρόπο:

Κάντε κλικ στο κόκκινο μπλοκ - θα δείτε το αποτέλεσμα:

Βύθιση

Εκτός από τη φούσκα των γεγονότων, υπάρχει και κατάδυση(σύμφωνα με επιστημονικά στάδιο υποκλοπής). Αυτό σημαίνει ότι το συμβάν πρώτα πηγαίνει από πάνω προς τα κάτω (στάδιο τομής), φτάνει στο στοιχείο μας (στάδιο στόχος) και μόνο μετά αρχίζει να επιπλέει (στάδιο φυσαλίδων).

Μπορείτε να κρεμάσετε έναν χειριστή συμβάντων λαμβάνοντας υπόψη το στάδιο της υποκλοπής μόνο με τη βοήθεια του addEventListener. Για να γίνει αυτό, έχει μια τρίτη παράμετρο: εάν είναι αληθές, το συμβάν θα ενεργοποιηθεί στο στάδιο της παρακολούθησης και εάν είναι false, στο στάδιο της φυσαλίδας (αυτό είναι από προεπιλογή):

Vargreen = document.getElementById("πράσινο"); green.addEventListener("κλικ", func, true); func(γεγονός) ( )

Το στάδιο στο οποίο συνέβη ένα συμβάν μπορεί να προσδιοριστεί χρησιμοποιώντας την ιδιότητα συμβάν.eventPhase. Μπορεί να λάβει τις ακόλουθες τιμές: 1 - στάδιο αναχαίτισης, 2 - στάδιο στόχου, 3 - στάδιο ανόδου.

Εισαγωγή στην Αντιπροσωπεία

Φανταστείτε μια κατάσταση: ας έχουμε ulΜε αρκετές li. Το ακόλουθο συμβάν επισυνάπτεται σε κάθε li: όταν κάνετε κλικ στο li, το "!" προστίθεται στο τέλος του.

Ας εφαρμόσουμε τα παραπάνω:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
var li = document.querySelectorAll("#ul li"); //Στο βρόχο, κρεμάμε τη συνάρτηση addSign σε κάθε li: for (var i = 0; i

Κάντε κλικ στο li - θα δείτε πώς προστίθεται το "!" στο τέλος τους:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5

Ας έχουμε τώρα και ένα κουμπί, κάνοντας κλικ στο οποίο προστίθεται ένα νέο στο τέλος του ul liμε το κείμενο «αντικείμενο». Μας περιμένει μια έκπληξη: η συνημμένη εκδήλωση δεν θα λειτουργήσει για καινούργια li! Ας βεβαιωθούμε για αυτό:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5

Κάντε κλικ στο κουμπί για να προσθέσετε li και στη συνέχεια σε αυτό το νέο li - δεν θα αντιδράσει:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
Προσθέστε li

Για να λύσετε το πρόβλημα, τη στιγμή της δημιουργίας ενός νέου li, κρεμάστε μια συνάρτηση σε αυτό addSignμέσω του addEventListener. Ας το εφαρμόσουμε:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
var li = document.querySelectorAll("#ul li"); για (var i = 0; i

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
Προσθέστε li

Υπάρχει ένας δεύτερος τρόπος για να αντιμετωπιστεί το πρόβλημα - η ανάθεση εκδηλώσεων. Ας το αναλύσουμε.

Αντιπροσωπεία εκδήλωσης

Η ουσία της αντιπροσωπείας είναι η εξής: θα κρεμάσουμε μια εκδήλωση όχι σε κάθε λι, αλλά στον γονέα τους - στις ul.

Ταυτόχρονα, θα πρέπει να διατηρηθεί η απόδοση του σεναρίου μας: όπως και πριν, όταν κάνουμε κλικ στο li, θα προστεθεί στο τέλος του το "!". Μόνο το συμβάν στη νέα έκδοση θα αναρτηθεί στο ul:

var ul = document.getElementById("ul"); //Κρέμασε το συμβάν στο ul: ul.addEventListener("click", addSign); συνάρτηση addSign() ( )

Πώς το κάνουμε αυτό: αφού το συμβάν είναι αναρτημένο στο ul, μέσα στη συνάρτηση μπορούμε να πιάσουμε το li με συμβάν.στόχος. Επιτρέψτε μου να σας υπενθυμίσω τι είναι το event.target - αυτή είναι ακριβώς η ετικέτα στην οποία έγινε το κλικ, στην περίπτωσή μας είναι li.

Λοιπόν, εδώ είναι η λύση στο πρόβλημά μας μέσω της αντιπροσωπείας:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5

Αποτέλεσμα εκτέλεσης κώδικα:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5

Σε αυτήν την περίπτωση, η λύση μας θα λειτουργήσει αυτόματα ακόμα και για νέα λι, επειδή η εκδήλωση δεν αναρτάται στο li, αλλά στο ul:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
var ul = document.getElementById("ul"); ul.addEventListener("κλικ", addSign); συνάρτηση addSign() ( event.target.innerHTML = event.target.innerHTML + "!"; ) //Εφαρμογή του κουμπιού για προσθήκη νέου li: κουμπί var = document.getElementById("κουμπί"); button.addEventListener("κλικ", addLi); συνάρτηση addLi() ( var li = document.createElement("li"); li.innerHTML = "new li"; ul.appendChild(li); )

Κάντε κλικ στο κουμπί για να προσθέσετε li και στη συνέχεια σε αυτό το νέο li - θα αντιδράσει:

  • παράγραφος 1
  • σημείο 2
  • σημείο 3
  • σημείο 4
  • σημείο 5
Προσθέστε li

Ο κώδικας μας λειτουργεί, αλλά όχι χωρίς ελαττώματα. Ας αναλύσουμε αυτές τις ελλείψεις και ας γράψουμε μια πιο καθολική λύση.

Αντιπροσωπεία γενικής εκδήλωσης

Το μειονέκτημα του κώδικα μας θα εκδηλωθεί όταν υπάρχουν κάποιες ένθετες ετικέτες μέσα στο li. Στην περίπτωσή μας, ας είναι ετικέτες Εγώ:

Σε αυτή την περίπτωση, πατώντας Εγώθα έχει ως αποτέλεσμα να προστεθεί ένα θαυμαστικό τέλος του i tag, όχι ετικέτα li, όπως θα θέλαμε (αν κάνετε κλικ στο li εκτός πλάγιας γραφής, τότε όλα θα πάνε καλά):

  • παράγραφος πλάγια γραφή 1
  • παράγραφος πλάγια γραφή 2
  • παράγραφος πλάγια γραφή 3
  • παράγραφος πλάγια γραφή 4
  • παράγραφος πλάγια γραφή 5
var ul = document.getElementById("ul"); ul.addEventListener("κλικ", addSign); συνάρτηση addSign() ( event.target.innerHTML = event.target.innerHTML + "!"; )

Κάντε κλικ στα πλάγια γράμματα - θα δείτε πώς "!" θα προστεθεί στο τέλος του (πατώντας εκτός των πλάγιων γραμμάτων θα λειτουργήσει καλά):

Το πρόβλημα επιλύεται ως εξής (η περιγραφόμενη μέθοδος δεν είναι η μόνη, αλλά η απλούστερη): χρησιμοποιώντας την πλησιέστερη μέθοδο, βρίσκουμε το πλησιέστερο li, που είναι ο γονέας του event.target ως εξής: event.target.closest("li").

Πώς λειτουργεί: εάν το κλικ ήταν ενεργοποιημένο Εγώ, μετά μέσα συμβάν.στόχοςαυτό λέω ψέματα, και μέσα event.target.closest("li")- το λι μας για το οποίο η εκδήλωση θα πρέπει να πυροδοτηθεί.

Εάν το κλικ ήταν στο li, μετά μέσα συμβάν.στόχος, και στο event.target.closest("li")το λι μας θα πει ψέματα.

Ας ελέγξουμε:

  • παράγραφος πλάγια γραφή 1
  • παράγραφος πλάγια γραφή 2
  • παράγραφος πλάγια γραφή 3
  • παράγραφος πλάγια γραφή 4
  • παράγραφος πλάγια γραφή 5
var ul = document.getElementById("ul"); ul.addEventListener("click", function(event) ( var li = event.target.closest("li"); if (li) ( //ελέγξτε αν δεν υπάρχει καθόλου γονικός li.innerHTML = li.innerHTML + "!";) ));

Αποτέλεσμα εκτέλεσης κώδικα:

Ανεξάρτητα από το πόσο βαθιά φωλιάζει: tag Εγώμπορεί να είναι σε μια ετικέτα σι, και αυτό στην ετικέτα σπιθαμήκαι μόνο τότε μέσα li- δεν πειράζει: κατασκευή event.target.closest("li")θα βρει τον γονέα από οποιοδήποτε επίπεδο φωλιάς.

Όταν συμβαίνει ένα συμβάν, οι χειριστές πυροβολούν πρώτα στο ίδιο το ένθετο στοιχείο, μετά στο μητρικό του στοιχείο, μετά πάνω και ούτω καθεξής, πάνω στην αλυσίδα ένθεσης.

Για παράδειγμα, υπάρχουν 3 ένθετα στοιχεία FORM > DIV > P , με έναν χειριστή σε καθένα:

Ο κώδικας: ΜΟΡΦΗ

DIV

Οι φυσαλίδες διασφαλίζουν ότι ένα κλικ στο εσωτερικό

Θα καλέσει τον χειριστή onclick (εάν υπάρχει) πρώτα στο

Επομένως, εάν κάνετε κλικ στο P στο παραπάνω παράδειγμα, τότε η ειδοποίηση θα εμφανίζεται διαδοχικά: p → div → φόρμα.

Αυτή η διαδικασία ονομάζεται φυσαλίδες επειδή τα γεγονότα που αναβλύζουν από το εσωτερικό στοιχείο προς τα πάνω μέσω των γονέων, όπως μια φυσαλίδα αέρα επιπλέει στο νερό.

συμβάν.στόχος

Σε όποιο στοιχείο κι αν πιάσουμε το συμβάν, μπορείτε πάντα να μάθετε πού ακριβώς συνέβη.
Το βαθύτερο στοιχείο που ενεργοποιεί το συμβάν ονομάζεται στοιχείο "στόχος" ή "πηγή" και είναι διαθέσιμο ως event.target.

Διαφορές από αυτό (=event.currentTarget):

  • Το event.target είναι το στοιχείο πηγής στο οποίο συνέβη το συμβάν, παραμένει αμετάβλητο κατά τη διαδικασία δημιουργίας φυσαλίδων.
  • Αυτό είναι το τρέχον στοιχείο στο οποίο έφτασε η φυσαλίδα, το οποίο εκτελεί αυτήν τη στιγμή ο χειριστής σε αυτό.

Για παράδειγμα, εάν υπάρχει μόνο ένας χειριστής form.onclick, τότε θα "πιάσει" όλα τα κλικ μέσα στη φόρμα. Όπου υπάρχει ένα κλικ μέσα - θα εμφανιστεί στο στοιχείο

Αυτό στο οποίο θα τρέξει ο χειριστής.

Εν:

  • αυτό (=event.currentTarget) θα είναι πάντα η ίδια η φόρμα, αφού ο χειριστής πυροβόλησε πάνω της.
  • Το event.target θα περιέχει έναν σύνδεσμο προς ένα συγκεκριμένο στοιχείο μέσα στη φόρμα, το πιο ένθετο στο οποίο έγινε κλικ.

Είναι επίσης πιθανό το event.target και αυτό να είναι το ίδιο στοιχείο, για παράδειγμα, εάν δεν υπάρχουν άλλες ετικέτες στη φόρμα και το κλικ έγινε στο ίδιο το στοιχείο .

Σταματήστε να δημιουργείτε ένα συμβάν

Η ανάβαση πηγαίνει ευθεία προς τα πάνω. Κανονικά το συμβάν θα εμφανίζεται με φυσαλίδες μέχρι το στοιχείο , και στη συνέχεια μέχρι το έγγραφο , και μερικές φορές ακόμη και το παράθυρο , καλώντας όλους τους χειριστές στο πέρασμά του.

Αλλά οποιοδήποτε ενδιάμεσο λογισμικό μπορεί να αποφασίσει ότι το συμβάν έχει υποβληθεί σε πλήρη επεξεργασία και να σταματήσει τη δημιουργία φυσαλίδων.

Για να σταματήσετε τις φυσαλίδες, πρέπει να καλέσετε τη μέθοδο event.stopPropagation().

Για παράδειγμα, εδώ, όταν κάνετε κλικ στο κουμπί, ο χειριστής σώμα.ονκλικδεν θα λειτουργήσει:

Ο κώδικας:

Παρακολούθηση εκδήλωσης. event.stopImmediatePropagation()

Εάν ένα στοιχείο έχει πολλούς χειριστές για ένα συμβάν, τότε ακόμα και αν σταματήσει η φυσαλίδα, θα εκτελεστούν όλοι.

Αυτό είναι, διακοπή Διάδοσηςαποτρέπει την περαιτέρω εξέλιξη του συμβάντος, αλλά στο τρέχον στοιχείο, όλοι οι χειριστές θα λειτουργήσουν.

Για να σταματήσετε εντελώς την επεξεργασία, σύγχρονα προγράμματα περιήγησηςμέθοδος υποστήριξης event.stopImmediatePropagation(). Όχι μόνο αποτρέπει τη δημιουργία φυσαλίδων, αλλά και σταματά την επεξεργασία συμβάντων στο τρέχον στοιχείο.

Διαφορές IE8

Για να διευκολυνθεί η πλοήγηση, έχω συλλέξει τις διαφορές IE8 που έχουν να κάνουν με τη δημιουργία φυσαλίδων σε μία ενότητα.

Οι γνώσεις τους θα χρειαστούν εάν αποφασίσετε να γράψετε σε καθαρό JS, χωρίς πλαίσια και χρειάζεστε υποστήριξη IE8.

Δεν υπάρχει ιδιότητα event.currentTarget

Σημειώστε ότι κατά την εκχώρηση ενός προγράμματος χειρισμού μέσω της ιδιότητας on, έχουμε αυτό , επομένως το event.currentTarget συνήθως δεν χρειάζεται, αλλά όταν εκχωρείται μέσω του attachEvent , ο χειριστής δεν το λαμβάνει, επομένως το τρέχον στοιχείο, εάν χρειάζεται, μπορεί να ληφθεί μόνο από κλεισίματα.

Το Event.srcElement χρησιμοποιείται αντί του event.target στον IE8

Εάν γράφουμε ένα πρόγραμμα χειρισμού που θα υποστηρίζει τόσο IE8 όσο και σύγχρονα προγράμματα περιήγησης, τότε μπορούμε να το ξεκινήσουμε ως εξής:

Κωδικός: elem.onclick = συνάρτηση(γεγονός) (
συμβάν = συμβάν || window.event;
var target = συμβάν.στόχος || event.srcElement;

// ... τώρα έχουμε ένα αντικείμενο συμβάντος και έναν στόχο
...
}

Για να σταματήσετε τη δημιουργία φυσαλίδων χρησιμοποιήστε τον κώδικα event.cancelBubble=true

Μπορείτε να σταματήσετε το αναδυόμενο πρόγραμμα περιήγησης ως εξής:

Κωδικός: event.stop Διάδοση ? event.stopPropagation() : (event.cancelBubble=true);

Σύνολο

  • Όταν συμβαίνει ένα συμβάν, το στοιχείο στο οποίο συνέβη επισημαίνεται ως "στόχος" (event.target).
  • Στη συνέχεια, το συμβάν κατευθύνεται αρχικά από τη ρίζα του εγγράφου στο event.target , καλώντας τους χειριστές που παρέχονται μέσω του addEventListener(...., true) στην πορεία.
  • Στη συνέχεια, το συμβάν ταξιδεύει από το event.target μέχρι τη ρίζα του εγγράφου, καλώντας τους χειριστές στην πορεία, που παρέχεται μέσω του on* και του addEventListener(..., false).
  • Το event.target είναι το βαθύτερο στοιχείο στο οποίο συνέβη το συμβάν.
  • event.currentTarget (=this) – το στοιχείο στο οποίο ενεργοποιείται αυτήν τη στιγμή ο χειριστής (στο οποίο το συμβάν «επιπλέει»).
  • event.eventPhase - σε ποια φάση λειτούργησε (κατάδυση = 1, ανάβαση = 3).

Τα συμβάντα είναι ενέργειες ή περιστατικά που συμβαίνουν στο σύστημα που προγραμματίζετε και για το οποίο σας ενημερώνει το σύστημα μπορείςανταποκριθείτε σε αυτά με κάποιο τρόπο εάν το επιθυμείτε. Για παράδειγμα, εάν ο χρήστης κάνει κλικ σε ένα κουμπί σε μια ιστοσελίδα, ίσως θελήσετε να απαντήσετε σε αυτήν την ενέργεια εμφανίζοντας ένα πλαίσιο πληροφοριών. Σε αυτό το άρθρο, συζητάμε μερικές σημαντικές έννοιες των γύρω συμβάντων και εξετάζουμε πώς λειτουργούν στα προγράμματα περιήγησης. Αυτή δεν θα είναι μια εξαντλητική μελέτη· αυτό ακριβώς που πρέπει να γνωρίζετε σε αυτό το στάδιο.

Προαπαιτούμενα: Βασική γνώση υπολογιστών, βασική κατανόηση HTML και CSS, JavaScript πρώτα βήματα .
σκοπός: Για να κατανοήσετε τη θεμελιώδη θεωρία των γεγονότων, πώς λειτουργούν σε προγράμματα περιήγησης και πώς μπορεί να διαφέρουν τα γεγονότα σε διαφορετικά περιβάλλοντα προγραμματισμού.

Μια σειρά από τυχερά γεγονότα

όπως παραπάνω, εκδηλώσειςείναι ενέργειες ή περιστατικά που συμβαίνουν στο σύστημα που προγραμματίζετε - το σύστημα παράγει (ή "πυροδοτεί") ένα σήμα κάποιου είδους όταν συμβαίνει ένα γεγονός και παρέχει επίσης έναν μηχανισμό με τον οποίο μπορεί να πραγματοποιηθεί αυτόματα κάποιο είδος ενέργειας (δηλ. , εκτελείται κάποιος κώδικας) όταν συμβαίνει το συμβάν. Για παράδειγμα, σε ένα αεροδρόμιο, όταν ο διάδρομος είναι καθαρός για να απογειωθεί ένα αεροπλάνο, επικοινωνείται ένα σήμα στον πιλότο και ως αποτέλεσμα, αρχίζουν να πιλοτάρουν το αεροπλάνο.

Στην περίπτωση του Ιστού, τα συμβάντα ενεργοποιούνται μέσα στο παράθυρο του προγράμματος περιήγησης και τείνουν να συνδέονται με ένα συγκεκριμένο στοιχείο που βρίσκεται σε αυτό - αυτό μπορεί να είναι ένα μεμονωμένο στοιχείο, σύνολο στοιχείων, το έγγραφο HTML που έχει φορτωθεί στην τρέχουσα καρτέλα ή ολόκληρο το παράθυρο του προγράμματος περιήγησης. Υπάρχουν πολλοί διαφορετικοί τύποι γεγονότων που μπορούν να συμβούν, για παράδειγμα:

  • Ο χρήστης κάνει κλικ με το ποντίκι πάνω από ένα συγκεκριμένο στοιχείο ή τοποθετεί το δείκτη του ποντικιού πάνω από ένα συγκεκριμένο στοιχείο.
  • Ο χρήστης πατά ένα πλήκτρο στο πληκτρολόγιο.
  • Ο χρήστης αλλάζει μέγεθος ή κλείνει το παράθυρο του προγράμματος περιήγησης.
  • Υποβάλλεται έντυπο.
  • Ένα βίντεο που αναπαράγεται ή τίθεται σε παύση ή ολοκληρώνεται η αναπαραγωγή.
  • Παρουσιάστηκε σφάλμα.

Μπορείτε να συλλέξετε από αυτό (και ρίχνοντας μια ματιά στην αναφορά του MDN Event) που υπάρχουν πολύτων γεγονότων που μπορούν να ανταποκριθούν.

Κάθε διαθέσιμη εκδήλωση έχει ένα χειριστής συμβάντων, το οποίο είναι ένα μπλοκ κώδικα (συνήθως μια συνάρτηση JavaScript που δημιουργείτε εσείς ως προγραμματιστής) που θα εκτελεστεί κατά την ενεργοποίηση του συμβάντος. Όταν ένα τέτοιο μπλοκ κώδικα ορίζεται να εκτελείται ως απόκριση σε ένα συμβάν που πυροδοτείται, λέμε ότι είμαστε εγγραφή ενός χειριστή συμβάντων. Σημειώστε ότι μερικές φορές καλούνται οι χειριστές συμβάντων ακροατές εκδηλώσεων- είναι σχεδόν εναλλάξιμα για τους σκοπούς μας, αν και αυστηρά μιλώντας, συνεργάζονται. Ο ακροατής ακούει για το γεγονός που συμβαίνει και ο χειριστής είναι ο κώδικας που εκτελείται ως απόκριση σε αυτό που συμβαίνει.

Σημείωση: Τα συμβάντα Ιστού δεν αποτελούν μέρος της βασικής γλώσσας JavaScript - ορίζονται ως μέρος των API που είναι ενσωματωμένα στο πρόγραμμα περιήγησης.

Ένα απλό παράδειγμα

Ας δούμε ένα απλό παράδειγμα για να εξηγήσουμε τι εννοούμε εδώ. Έχετε ήδη δει συμβάντα και χειριστές συμβάντων που χρησιμοποιούνται ήδη σε πολλά από τα παραδείγματα αυτού του μαθήματος, αλλά ας ανακεφαλαιώσουμε απλώς για να εμπεδώσουμε τις γνώσεις μας. Στο παρακάτω παράδειγμα , έχουμε ένα single , το οποίο όταν πατηθεί, αλλάζει το φόντο σε ένα τυχαίο χρώμα:

Κουμπί (περιθώριο: 10 px);

Το JavaScript μοιάζει με αυτό:

Const btn = document.querySelector("button"); συνάρτηση random(number) ( return Math.floor(Math.random() * (number+1)); ) btn.onclick = function() (const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; )

Σε αυτόν τον κώδικα, αποθηκεύουμε μια αναφορά στο κουμπί μέσα σε μια σταθερά που ονομάζεται btn, χρησιμοποιώντας τη συνάρτηση Document.querySelector(). Ορίζουμε επίσης μια συνάρτηση που επιστρέφει έναν τυχαίο αριθμό. Το τρίτο μέρος του κώδικα είναι ο χειριστής συμβάντων. Η σταθερά btn δείχνει α συνάρτηση bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; )

Η παλαιότερη μέθοδος καταχώρισης των χειριστών συμβάντων που βρέθηκαν στον Ιστό Χαρακτηριστικά HTML του χειριστή συμβάντωνενσωματωμένοι χειριστές συμβάντων) όπως αυτό που φαίνεται παραπάνω - η τιμή του χαρακτηριστικού είναι κυριολεκτικά ο κώδικας JavaScript που θέλετε να εκτελέσετε όταν συμβεί το συμβάν. Το παραπάνω παράδειγμα καλεί μια συνάρτηση που ορίζεται μέσα σε ένα στοιχείο που χρησιμοποιείται για την ενσωμάτωση ή την αναφορά εκτελέσιμου κώδικα. Αυτό χρησιμοποιείται συνήθως για την ενσωμάτωση ή αναφορά σε κώδικα JavaScript.">

Οι περισσότεροι χειριστές συμβάντων που θα συναντήσετε έχουν απλώς ένα τυπικό σύνολο ιδιοτήτων και συναρτήσεων (μεθόδων) διαθέσιμο στο αντικείμενο συμβάντος. Ανατρέξτε στην αναφορά αντικειμένου συμβάντος για μια πλήρη λίστα. Ορισμένοι πιο προηγμένοι χειριστές, ωστόσο, προσθέτουν ειδικές ιδιότητες που περιέχουν επιπλέον δεδομένα που Πρέπει να λειτουργήσει. Το Media Recorder API, για παράδειγμα, έχει ένα συμβάν με διαθεσιμότητα δεδομένων, το οποίο ενεργοποιείται όταν έχει εγγραφεί κάποιος ήχος ή βίντεο και είναι διαθέσιμο για να κάνετε κάτι με (για παράδειγμα, αποθήκευση ή αναπαραγωγή του). έχει διαθέσιμη μια ιδιότητα δεδομένων που περιέχει τα εγγεγραμμένα δεδομένα ήχου ή βίντεο για να σας επιτρέψει να έχετε πρόσβαση σε αυτά και να κάνετε κάτι με αυτό.

Αποτροπή προεπιλεγμένης συμπεριφοράς

Μερικές φορές, θα συναντήσετε μια κατάσταση όπου θέλετε να αποτρέψετε ένα συμβάν να κάνει αυτό που κάνει από προεπιλογή. Το πιο συνηθισμένο παράδειγμα είναι αυτό μιας φόρμας ιστού, για παράδειγμα, μιας προσαρμοσμένης φόρμας εγγραφής. Όταν συμπληρώνετε τις λεπτομέρειες και πατήστε το κουμπί υποβολή, η φυσική συμπεριφορά είναι τα δεδομένα να υποβάλλονται σε μια καθορισμένη σελίδα στο διακομιστή για επεξεργασία και το πρόγραμμα περιήγησης να ανακατευθύνεται σε μια σελίδα "μηνύματος επιτυχίας" κάποιου είδους (ή στην ίδια σελίδα, εάν υπάρχει άλλη Δεν διευκρινίζεται.)

Το πρόβλημα προκύπτει όταν ο χρήστης δεν έχει υποβάλει σωστά τα δεδομένα - ως προγραμματιστής, θέλετε να αποτρέψετε την υποβολή στον διακομιστή και να δώσετε ένα μήνυμα σφάλματος που λέει τι είναι λάθος και τι πρέπει να γίνει για να διορθωθούν τα πράγματα. Ορισμένα προγράμματα περιήγησης υποστηρίζουν λειτουργίες αυτόματης επικύρωσης δεδομένων φόρμας, αλλά επειδή πολλοί δεν το κάνουν, σας συμβουλεύουμε να μην βασίζεστε σε αυτές και να εφαρμόσετε τους δικούς σας ελέγχους επικύρωσης. Ας δούμε ένα απλό παράδειγμα.

Αρχικά, μια απλή φόρμα HTML που απαιτεί να εισαγάγετε το όνομα και το επώνυμό σας:

Div (περιθώριο-κάτω: 10 px; )

Τώρα λίγο JavaScript - εδώ υλοποιούμε έναν πολύ απλό έλεγχο μέσα σε έναν χειριστή συμβάντων onsubmit (το συμβάν υποβολής ενεργοποιείται σε μια φόρμα όταν υποβάλλεται) που ελέγχει εάν τα πεδία κειμένου είναι άδεια. Εάν είναι, καλούμε τη συνάρτηση preventDefault() στο αντικείμενο συμβάντος - το οποίο σταματά την υποβολή της φόρμας - και μετά εμφανίζουμε ένα μήνυμα σφάλματος στην παράγραφο κάτω από τη φόρμα μας για να πούμε στον χρήστη τι συμβαίνει:

Const form = document.querySelector("form"); const fname = document.getElementById("fname"); const lname = document.getElementById("lname"); const para = document.querySelector("p"); form.onsubmit = function(e) ( if (fname.value === "" || lname.value === "") ( e.preventDefault(); para.textContent = "Πρέπει να συμπληρώσετε και τα δύο ονόματα! ";))

Προφανώς, πρόκειται για αρκετά αδύναμη επικύρωση φόρμας - δεν θα εμπόδιζε τον χρήστη να επικυρώνει τη φόρμα με κενά ή αριθμούς που έχουν εισαχθεί στα πεδία, για παράδειγμα - αλλά είναι εντάξει για παράδειγμα. Η έξοδος είναι η εξής:

Συμβάν με φυσαλίδες και καταγραφή

Το τελευταίο θέμα που θα καλύψουμε εδώ είναι κάτι που δεν θα συναντήσετε συχνά, αλλά μπορεί να είναι πραγματικός πόνος αν δεν το καταλαβαίνετε. Η δημιουργία φυσαλίδων και η καταγραφή συμβάντων είναι δύο μηχανισμοί που περιγράφουν τι συμβαίνει όταν δύο χειριστές του ίδιου τύπου συμβάντος ενεργοποιούνται σε ένα στοιχείο. Ας δούμε ένα παράδειγμα για να το κάνουμε πιο εύκολο - ανοίξτε το παράδειγμα show-video-box.html σε μια νέα καρτέλα (και σε μια άλλη καρτέλα.) Είναι επίσης διαθέσιμο ζωντανά παρακάτω:

Παράδειγμα κρυφού βίντεο
Εμφάνιση παραδείγματος κουτιού βίντεο

Αυτό είναι ένα πολύ απλό παράδειγμα που δείχνει και αποκρύπτει το a ) είναι το γενικό δοχείο για το περιεχόμενο ροής. Δεν έχει καμία επίδραση στο περιεχόμενο ή τη διάταξη έως ότου γίνει στυλ χρησιμοποιώντας CSS.">

με a ) ενσωματώνει μια συσκευή αναπαραγωγής πολυμέσων που υποστηρίζει την αναπαραγωγή βίντεο στο έγγραφο. Μπορείς να χρησιμοποιήσεις