Εισαγωγή στα αναδυόμενα συμβάντα. Προηγμένη εργασία με το αντικείμενο συμβάντος στο JavaScript Ακύρωση συμβάντος φυσαλίδες js

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

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

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

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

Θα δείξουμε την εμφάνιση ενός συμβάντος (φούσκα) χρησιμοποιώντας το ακόλουθο παράδειγμα:

Επικεφαλίδα

Κάποιο πολύ σημαντικό κείμενο

Κεφάλαιο

Κάποιο κείμενο

Το υπόλοιπο κείμενο

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

document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); for (var i=0; i< allElements.length; i++) { allElements[i].addEventListener("click",function() {console.log(this.tagName);},false); }; document.addEventListener("click",function() {console.log(this);},false); window.addEventListener("click",function() {console.log(this);},false); });

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

Πώς να διακόψετε τη δημιουργία φυσαλίδων συμβάντων

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

Για παράδειγμα, ας αλλάξουμε το παραπάνω παράδειγμα, ώστε το συμβάν να μην εμφανίζεται με φυσαλίδες πάνω από το σώμα: document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); για (var i=0 ; Εγώ

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

Λήψη του στοιχείου που κάλεσε τον χειριστή

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

Για παράδειγμα, ας εμφανίσουμε στην κονσόλα το αναγνωριστικό του στοιχείου που κάλεσε τον χειριστή συμβάντων:

Var myP = document.getElementById("myP"); myP.addEventListener("click",function())( //πάρτε το στοιχείο DOM που κάλεσε τον χειριστή συμβάντων - αυτό //πάρτε το αναγνωριστικό του και εξάγετε το στην κονσόλα console.log(this.id); ));

Μπορείτε επίσης να χρησιμοποιήσετε την ιδιότητα currentTarget (event.currentTarget) για να λάβετε το τρέχον στοιχείο.

Στάδια (φάσεις) της εκδήλωσης

Πριν αρχίσει να εμφανίζεται ένα γεγονός (το στάδιο ανόδου), περνά πρώτα από 2 ακόμη στάδια:

  • Το στάδιο 1 είναι το στάδιο της εμβάπτισης στο στοιχείο που δημιούργησε το συμβάν. Εκείνοι. σε αυτό το στάδιο υπάρχει μια κίνηση από πάνω προς τα κάτω, δηλ. από αντικείμενο παραθύρουσε στοιχείο. Αυτό το στάδιο ονομάζεται επίσης στάδιο υποκλοπής.
  • Το στάδιο 2 είναι το στάδιο της επίτευξης του στόχου, δηλ. στοιχείο (αντικείμενο) που δημιούργησε το συμβάν.

Λαμβάνοντας υπόψη όλα τα στάδια που περνά ένα γεγονός, προκύπτει η παρακάτω εικόνα:

Ας τροποποιήσουμε το παραπάνω παράδειγμα σενάριο ως εξής:

Document.addEventListener("DOMContentLoaded", function() ( var allElements = document.getElementsByTagName("*"); για (var i=0; i

Η τρίτη παράμετρος των μεθόδων addEventListener και removeEventListener καθορίζει το στάδιο στο οποίο θα καταγραφεί το συμβάν. Αν αυτή η παράμετροςέχει οριστεί σε true , το συμβάν θα παρεμποδιστεί στο στάδιο εμβάπτισης συμβάντος (παρακολούθηση). Και αν η παράμετρος είναι ψευδής , τότε το συμβάν θα υποκλαπεί στο στάδιο των φυσαλίδων. Για να χειριστείτε το συμβάν στον ίδιο τον στόχο, μπορείτε να χρησιμοποιήσετε τη μέθοδο addEventListener όπως και με τιμή ψευδής, και με την τιμή true .

Προσοχή: κατά τη διάρκεια του σταδίου εμβάπτισης (interception), τα συμβάντα μπορούν να υποκλαπούν μόνο από χειριστές που έχουν προστεθεί χρησιμοποιώντας τη μέθοδο addEventListener(). Προστέθηκαν χειριστές χρησιμοποιώντας άλλες μεθόδους ( Χαρακτηριστικό HTMLή μέσω JavaScript χρησιμοποιώντας την ιδιότητα on[event]) μπορεί να υποκλέψει συμβάντα μόνο στο στάδιο της δημιουργίας φυσαλίδων.

Λήψη του στοιχείου που δημιούργησε το συμβάν

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

Εξετάστε το παραπάνω παράδειγμα, στο οποίο αλλάζουμε το περιεχόμενο του στοιχείου σεναρίου στο εξής:

Document.addEventListener("DOMContentLoaded", function() ( var elementBody = document.body; elementBody.addEventListener("click",function())( console.log(this.tagName + " - το στοιχείο που κάλεσε τον χειριστή") ; κονσόλα .log(event.currentTarget.tagName + " - το στοιχείο που κάλεσε τον χειριστή"); console.log(event.target.tagName + " - το στοιχείο που δημιούργησε το συμβάν"); ),false); )) ;

Ας δείξουμε το παράδειγμά μας κάνοντας αριστερό κλικ στην περιοχή που ανήκει στο ισχυρό στοιχείο:

Όλα ξεκίνησαν με τη χρήση JavaScript και κλάσεων.

Ωστόσο, έχω ένα πρόβλημα. Ήθελα να χρησιμοποιήσω κάτι που ονομάζεται Bubble Events, αλλά ήθελα επίσης να ελαχιστοποιήσω τις εξαρτήσεις που θα έπρεπε να εγχύσω. Δεν ήθελα να συνδεθώ Βιβλιοθήκες jQueryγια "αυτό το μικρό τεστ", απλώς για να χρησιμοποιήσετε αναδυόμενα συμβάντα.

Ας ρίξουμε μια πιο προσεκτική ματιά στο τι είναι τα toasting events, πώς λειτουργούν και μερικούς τρόπους για να τα εφαρμόσετε.

Εντάξει, ποιο είναι το πρόβλημα; Ας δούμε ένα απλό παράδειγμα:

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

Ας ξεκινήσουμε με το HTML:

  • Μολύβι
  • Στυλό
  • γόμα

Θα μπορούσα να χρησιμοποιήσω έναν τυπικό χειριστή συμβάντων JavaScript όπως αυτός:

For(var i = 0; i< buttons.length; i++) { var button = buttons[i]; button.addEventListener("click", function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }); }
Καλό φαίνεται... Αλλά δεν θα λειτουργήσει. Με τουλάχιστον, όχι όπως το περιμένουμε.

Το κλείσιμο κερδίζει Για όσους γνωρίζουν λίγο λειτουργικό JavaScript, το πρόβλημα είναι προφανές.

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

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

Αυτό που χρειαζόμαστε είναι ένα ξεχωριστό πλαίσιο για κάθε συνάρτηση:

Var buttons = document.querySelectorAll(".κουμπί γραμμής εργαλείων"); var createToolbarButtonHandler = function(button) ( return function() ( if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); ); ); for(var i = 0; i< buttons.length; i++) { buttons[i].addEventListener("click", createToolBarButtonHandler(buttons[i])); }
Πολύ καλύτερα! Και το πιο σημαντικό, λειτουργεί σωστά. Έχουμε δημιουργήσει μια συνάρτηση createToolbarButtonHandle που επιστρέφει ένα πρόγραμμα χειρισμού συμβάντων. Στη συνέχεια προσαρμόζουμε τον δικό μας χειριστή για κάθε κουμπί.

Ποιο ειναι το πρόβλημα? Φαίνεται καλό και λειτουργεί. Παρόλα αυτά, μπορούμε ακόμα να βελτιώσουμε τον κώδικά μας.

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

Αν όμως έχουμε κάτι σαν αυτό:

  • Foo
  • Μπαρ
  • // ...άλλα 997 στοιχεία...
  • baz

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

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

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

Var toolbarButtonHandler = συνάρτηση(ε) (κουμπί var = e.currentTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); ); for(var i = 0; i< buttons.length; i++) { button.addEventListener("click", toolbarButtonHandler); }
Εξαιρετική! Όχι μόνο απλοποιήσαμε τα πάντα σε μια μεμονωμένη συνάρτηση που χρησιμοποιείται πολλές φορές, αλλά κάναμε επίσης τον κώδικά μας πιο ευανάγνωστο αφαιρώντας μια περιττή συνάρτηση γεννήτριας.

Ωστόσο, μπορούμε ακόμα καλύτερα.

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

Μήπως υπάρχει άλλη προσέγγιση;

Ας ξεκινήσουμε κατανοώντας πώς λειτουργούν τα συμβάντα και πώς κινούνται κατά μήκος του DOM μας.

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

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

    Εδώ είναι το πρότυπο HTML μας:

    • Κουμπί Α
    • Κουμπί Β
    • Κουμπί Γ

    Όταν ο χρήστης κάνει κλικ στο κουμπί A, το συμβάν ταξιδεύει ως εξής:

    Αρχή
    | #έγγραφο
    | Φάση αναχαίτισης
    | HTML
    | ΣΩΜΑ
    | UL
    | LI#li_1
    | Κουμπί Α< - Событие возникает для целевого элемента
    | Φάση ανάβασης
    | LI#li_1
    | UL
    | ΣΩΜΑ
    | HTML
    v #document

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

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

    Ας πάρουμε τη γραμμή εργαλείων μας ως συγκεκριμένο παράδειγμα:

    Ul class="toolbar">

  • Μολύβι
  • Στυλό
  • γόμα

  • Τώρα που γνωρίζουμε ότι οποιοδήποτε κλικ στο κουμπί θα εμφανιστεί μέσω του στοιχείου ul.toolbar, ας συνδέσουμε το πρόγραμμα χειρισμού συμβάντων σε αυτό. Ευτυχώς το έχουμε ήδη:

    Var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("click", function(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. remove("ενεργό"); ));
    Τώρα έχουμε πολύ πιο καθαρό κώδικα, και έχουμε ξεφορτωθεί ακόμη και τους βρόχους! Σημειώστε ωστόσο ότι έχουμε αντικαταστήσει το e.currentTarget με το e.target . Ο λόγος έγκειται στο γεγονός ότι επεξεργαζόμαστε γεγονότα σε διαφορετικό επίπεδο.

    Το e.target είναι ο πραγματικός στόχος του συμβάντος, όπου περνάει μέσα από το DOM και από όπου θα εμφανιστεί στη συνέχεια.
    e.currentTarget - το τρέχον στοιχείο που χειρίζεται το συμβάν. Στην περίπτωσή μας, αυτό είναι το ul.toolbar.

    Βελτιωμένα συμβάντα Bubble αυτή τη στιγμήΔιαχειριζόμαστε οποιοδήποτε κλικ σε κάθε στοιχείο που εμφανίζεται μέσω του ul.toolbar , αλλά η συνθήκη επικύρωσής μας είναι πολύ απλή. Τι θα συνέβαινε αν είχαμε ένα πιο περίπλοκο DOM που περιλάμβανε εικονίδια και στοιχεία που δεν είχαν σχεδιαστεί για κλικ;

    • Μολύβι
    • Στυλό
    • γόμα

    Ωχ! Τώρα όταν κάνουμε κλικ στο li.separator ή το εικονίδιο, προσθέτουμε την κλάση .active σε αυτό. Τουλάχιστον, αυτό δεν είναι καλό. Χρειαζόμαστε έναν τρόπο να φιλτράρουμε τα γεγονότα έτσι ώστε να αντιδρούμε στο στοιχείο που χρειαζόμαστε.

    Ας δημιουργήσουμε μια μικρή βοηθητική συνάρτηση για αυτό:

    Var delegate = συνάρτηση(κριτήρια, ακροατής) ( return function(e) ( var el = e.target; do ( if (!criteria(el)) continue; e.delegateTarget = el; listener.apply(this, ορίσματα); επιστροφή; ) while((el = el.parentNode)); ); );
    Ο βοηθός μας κάνει δύο πράγματα. Αρχικά, θα επαναλάβει κάθε στοιχείο και τους γονείς του και θα ελέγξει εάν πληρούν την συνθήκη που πέρασε στην παράμετρο κριτηρίων. Εάν το στοιχείο ικανοποιεί, ο βοηθός προσθέτει ένα πεδίο στο αντικείμενο συμβάντος που ονομάζεται delegateTarget, το οποίο αποθηκεύει το στοιχείο που ικανοποιεί τις συνθήκες μας. Και μετά καλεί τον χειριστή. Αντίστοιχα, εάν κανένα στοιχείο δεν ικανοποιεί τη συνθήκη, δεν θα κληθεί κανένας χειριστής.

    Μπορούμε να το χρησιμοποιήσουμε ως εξής:

    Var toolbar = document.querySelector(".toolbar"); var buttonsFilter = function(elem) ( return elem.classList && elem.classList.contains("btn"); ); var buttonHandler = function(e) ( var button = e.delegateTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); ); toolbar.addEventListener("κλικ", delegate(buttonsFilter, buttonHandler));
    Ακριβώς αυτό που διέταξε ο γιατρός: ένας χειριστής συμβάντων προσαρτημένος σε ένα στοιχείο που κάνει όλη τη δουλειά. Αλλά το κάνει μόνο για τα στοιχεία που χρειαζόμαστε. Και ανταποκρίνεται τέλεια στην προσθήκη και αφαίρεση αντικειμένων από το DOM.

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

    Αν ήθελα να δημιουργήσω μια βιβλιοθήκη από αυτό ή να χρησιμοποιήσω τον κώδικα στην ανάπτυξη, θα πρόσθετα μερικά πράγματα:

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

    Κριτήρια Var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return kriter.isElement(e) && e.classList.contains(cls); ) ) //Περισσότερα κριτήρια);
    Η μερική χρήση του βοηθού θα ήταν επίσης χρήσιμη:

    Var partialDelgate = συνάρτηση(κριτήρια) ( return function(handler) ( return delgate(criteria, handler); ) );
    Αρχικό άρθρο: Κατανόηση των εκχωρημένων συμβάντων JavaScript
    (Από τον μεταφραστή: πρώτος μου, κρίνετε αυστηρά.)

    Καλή κωδικοποίηση!

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

    Προαπαιτούμενα: Σκοπός:
    Βασική γνώση υπολογιστών, βασική κατανόηση 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 δείχνει σε ένα στοιχείο και αυτός ο τύπος αντικειμένου έχει έναν αριθμό γεγονότων που μπορούν να ενεργοποιηθούν σε αυτό, και ως εκ τούτου, διαθέσιμοι χειριστές συμβάντων. Ακούμε την ενεργοποίηση του συμβάντος κλικ, ορίζοντας την ιδιότητα onclick event handler ώστε να ισούται με μια ανώνυμη συνάρτηση που περιέχει κώδικα που δημιουργεί ένα τυχαίο χρώμα RGB και ορίζει το χρώμα φόντου ίσο με αυτό.

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

    Το παράδειγμα εξόδου είναι το εξής:

    Δεν είναι μόνο ιστοσελίδες

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

    Ενσωματωμένοι χειριστές συμβάντων - μην τους χρησιμοποιείτε

    Μπορεί επίσης να δείτε ένα μοτίβο σαν αυτό στον κώδικά σας:

    Πατήστε με τη συνάρτηση bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol;)

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

    Πιέστε με

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

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

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

    Const buttons = document.querySelectorAll("button"); για (έστω i = 0; i< buttons.length; i++) { buttons[i].onclick = bgChange; } buttons.forEach(function(button) { button.onclick = bgChange; });

    Σημείωση: Ο διαχωρισμός της λογικής προγραμματισμού από το περιεχόμενό σας κάνει επίσης τον ιστότοπό σας πιο φιλικό στις μηχανές αναζήτησης.

    addEventListener() και removeEventListener()

    Ο νεότερος τύπος μηχανισμού συμβάντων ορίζεται στην Προδιαγραφή συμβάντων επιπέδου 2 του μοντέλου αντικειμένου εγγράφου (DOM), η οποία παρέχει στα προγράμματα περιήγησης μια νέα συνάρτηση - addEventListener() . Αυτό λειτουργεί με παρόμοιο τρόπο με τις ιδιότητες χειριστή συμβάντων, αλλά η σύνταξη είναι προφανώς διαφορετική. Θα μπορούσαμε να ξαναγράψουμε το παράδειγμά μας τυχαίου χρώματος για να μοιάζει με αυτό:

    Const btn = document.querySelector("button"); συνάρτηση bgChange() ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; ) btn.addEventListener("κλικ", bgChange);

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

    Btn.addEventListener("κλικ", function() ( var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body .style.backgroundColor = rndCol; ));

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

    Btn.removeEventListener("κλικ", bgChange);

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

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

    MyElement.onclick = functionA; myElement.onclick = functionB;

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

    MyElement.addEventListener("κλικ", functionA); myElement.addEventListener("κλικ", functionB);

    Και οι δύο συναρτήσεις θα εκτελούνται τώρα όταν γίνεται κλικ στο στοιχείο.

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

    Τι μηχανισμό να χρησιμοποιήσω;

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

    Τα άλλα δύο είναι σχετικά εναλλάξιμα, τουλάχιστον για απλές χρήσεις:

    • Οι ιδιότητες χειριστή συμβάντων έχουν λιγότερη ισχύ και επιλογές, αλλά καλύτερη συμβατότητα μεταξύ προγραμμάτων περιήγησης (υποστηρίζονται ήδη από Internet Explorer 8). Μάλλον θα πρέπει να ξεκινήσετε με αυτά καθώς μαθαίνετε.
    • Τα συμβάντα DOM Level 2 (addEventListener() , κ.λπ.) είναι πιο ισχυρά, αλλά μπορούν επίσης να γίνουν πιο περίπλοκα και υποστηρίζονται λιγότερο καλά (υποστηρίζονται ήδη από τον Internet Explorer 9). Θα πρέπει επίσης να πειραματιστείτε με αυτά και να στοχεύσετε να τα χρησιμοποιήσετε όπου είναι δυνατόν.

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

    Element.onclick = συνάρτηση1; element.onclick = function2; και τα λοιπά.

    Σημείωση: Εάν καλείστε να υποστηρίξετε προγράμματα περιήγησης παλαιότερα από τον Internet Explorer 8 στην εργασία σας, ενδέχεται να αντιμετωπίσετε δυσκολίες, καθώς αυτά τα αρχαία προγράμματα περιήγησης χρησιμοποιούν διαφορετικά μοντέλα συμβάντων από νεότερα προγράμματα περιήγησης. Αλλά ποτέ μην φοβάστε, οι περισσότερες βιβλιοθήκες JavaScript (για παράδειγμα jQuery) έχουν ενσωματωμένες λειτουργίες που αφαιρούν τις διαφορές μεταξύ των προγραμμάτων περιήγησης. Μην ανησυχείτε για αυτό πάρα πολύ σε αυτό το στάδιο του μαθησιακού σας ταξιδιού.

    Άλλες έννοιες εκδήλωσης

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

    Αντικείμενα συμβάντων

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

    Συνάρτηση bgChange(e) ( const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; e.target.style.backgroundColor = rndCol ; console.log(e); ) btn.addEventListener("κλικ", bgChange);

    Εδώ μπορείτε να δείτε ότι συμπεριλαμβάνουμε ένα αντικείμενο συμβάντος, e , στη συνάρτηση και στη συνάρτηση που ορίζει ένα στυλ χρώματος φόντου στο e.target - που είναι το ίδιο το κουμπί. Η ιδιότητα στόχος του αντικειμένου συμβάντος είναι πάντα μια αναφορά στο στοιχείο στο οποίο μόλις προέκυψε το συμβάν. Έτσι, σε αυτό το παράδειγμα, ορίζουμε ένα τυχαίο χρώμα φόντου στο κουμπί, όχι στη σελίδα.

    Σημείωση : Μπορείτε να χρησιμοποιήσετε οποιοδήποτε όνομα θέλετε για το αντικείμενο συμβάντος - απλά πρέπει να επιλέξετε ένα όνομα που μπορείτε στη συνέχεια να χρησιμοποιήσετε για να το αναφέρετε μέσα στη λειτουργία χειριστή συμβάντων. Το e/evt/event χρησιμοποιούνται πιο συχνά από προγραμματιστές επειδή είναι σύντομο και εύκολο να το θυμάστε. Είναι πάντα καλό να είσαι συνεπής - με τον εαυτό σου και με τους άλλους, αν είναι δυνατόν.

    Το e.target είναι απίστευτα χρήσιμο όταν θέλετε να ρυθμίσετε τον ίδιο χειριστή συμβάντων σε πολλά στοιχεία και να κάνετε κάτι σε όλα αυτά όταν συμβαίνει ένα συμβάν σε αυτά. Μπορεί, για παράδειγμα, να έχετε ένα σύνολο 16 πλακιδίων που εξαφανίζονται όταν κάνετε κλικ σε αυτά. Είναι χρήσιμο να μπορείτε πάντα να ορίζετε απλώς το πράγμα να εξαφανίζεται ως e.target, αντί να χρειάζεται να το επιλέξετε με κάποιον πιο δύσκολο τρόπο. Στο παρακάτω παράδειγμα (δείτε χρήσιμο-eventtarget.html για τον πλήρη πηγαίο κώδικα, δείτε επίσης να εκτελείται ζωντανά εδώ), δημιουργούμε 16 στοιχεία χρησιμοποιώντας JavaScript. Στη συνέχεια, τα επιλέγουμε όλα χρησιμοποιώντας το document.querySelectorAll() και, στη συνέχεια, κάνουμε βρόχο σε κάθε ένα, προσθέτοντας έναν onclick handler σε καθένα που το κάνει έτσι ώστε να εφαρμόζεται ένα τυχαίο χρώμα σε καθένα όταν γίνεται κλικ:

    Const divs = document.querySelectorAll("div"); για (έστω i = 0; i< divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } }

    Η έξοδος είναι η εξής (δοκιμάστε να κάνετε κλικ σε αυτό - διασκεδάστε):

    Κρυφό παράδειγμα Χρήσιμο παράδειγμα στόχου συμβάντος div ( ύψος: 100 px; πλάτος: 25%; float: αριστερά; ) για (έστω i = 1; i
  • Μολύβι
  • Στυλό
  • γόμα

  • Τώρα που γνωρίζουμε ότι οποιοδήποτε κλικ στο κουμπί θα εμφανιστεί μέσω του στοιχείου ul.toolbar, ας συνδέσουμε το πρόγραμμα χειρισμού συμβάντων σε αυτό. Ευτυχώς το έχουμε ήδη:

    Var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("click", function(e) ( var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList. remove("ενεργό"); ));
    Τώρα έχουμε πολύ πιο καθαρό κώδικα, και έχουμε ξεφορτωθεί ακόμη και τους βρόχους! Σημειώστε ωστόσο ότι έχουμε αντικαταστήσει το e.currentTarget με το e.target . Ο λόγος έγκειται στο γεγονός ότι επεξεργαζόμαστε γεγονότα σε διαφορετικό επίπεδο.

    Το e.target είναι ο πραγματικός στόχος του συμβάντος, όπου περνάει μέσα από το DOM και από όπου θα εμφανιστεί στη συνέχεια.
    e.currentTarget - το τρέχον στοιχείο που χειρίζεται το συμβάν. Στην περίπτωσή μας, αυτό είναι το ul.toolbar.

    Βελτιωμένα αναδυόμενα συμβάντα Επί του παρόντος χειριζόμαστε οποιοδήποτε κλικ σε κάθε στοιχείο που εμφανίζεται μέσω του ul.toolbar, αλλά η συνθήκη επικύρωσης είναι πολύ απλή. Τι θα συνέβαινε αν είχαμε ένα πιο περίπλοκο DOM που περιλάμβανε εικονίδια και στοιχεία που δεν είχαν σχεδιαστεί για κλικ;

    • Μολύβι
    • Στυλό
    • γόμα

    Ωχ! Τώρα όταν κάνουμε κλικ στο li.separator ή το εικονίδιο, προσθέτουμε την κλάση .active σε αυτό. Τουλάχιστον, αυτό δεν είναι καλό. Χρειαζόμαστε έναν τρόπο να φιλτράρουμε τα γεγονότα έτσι ώστε να αντιδρούμε στο στοιχείο που χρειαζόμαστε.

    Ας δημιουργήσουμε μια μικρή βοηθητική συνάρτηση για αυτό:

    Var delegate = συνάρτηση(κριτήρια, ακροατής) ( return function(e) ( var el = e.target; do ( if (!criteria(el)) continue; e.delegateTarget = el; listener.apply(this, ορίσματα); επιστροφή; ) while((el = el.parentNode)); ); );
    Ο βοηθός μας κάνει δύο πράγματα. Αρχικά, θα επαναλάβει κάθε στοιχείο και τους γονείς του και θα ελέγξει εάν πληρούν την συνθήκη που πέρασε στην παράμετρο κριτηρίων. Εάν το στοιχείο ικανοποιεί, ο βοηθός προσθέτει ένα πεδίο στο αντικείμενο συμβάντος που ονομάζεται delegateTarget, το οποίο αποθηκεύει το στοιχείο που ικανοποιεί τις συνθήκες μας. Και μετά καλεί τον χειριστή. Αντίστοιχα, εάν κανένα στοιχείο δεν ικανοποιεί τη συνθήκη, δεν θα κληθεί κανένας χειριστής.

    Μπορούμε να το χρησιμοποιήσουμε ως εξής:

    Var toolbar = document.querySelector(".toolbar"); var buttonsFilter = function(elem) ( return elem.classList && elem.classList.contains("btn"); ); var buttonHandler = function(e) ( var button = e.delegateTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active" ); ); toolbar.addEventListener("κλικ", delegate(buttonsFilter, buttonHandler));
    Ακριβώς αυτό που διέταξε ο γιατρός: ένας χειριστής συμβάντων προσαρτημένος σε ένα στοιχείο που κάνει όλη τη δουλειά. Αλλά το κάνει μόνο για τα στοιχεία που χρειαζόμαστε. Και ανταποκρίνεται τέλεια στην προσθήκη και αφαίρεση αντικειμένων από το DOM.

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

    Αν ήθελα να δημιουργήσω μια βιβλιοθήκη από αυτό ή να χρησιμοποιήσω τον κώδικα στην ανάπτυξη, θα πρόσθετα μερικά πράγματα:

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

    Κριτήρια Var = ( isElement: function(e) ( return e instanceof HTMLElement; ), hasClass: function(cls) ( return function(e) ( return kriter.isElement(e) && e.classList.contains(cls); ) ) //Περισσότερα κριτήρια);
    Η μερική χρήση του βοηθού θα ήταν επίσης χρήσιμη:

    Var partialDelgate = συνάρτηση(κριτήρια) ( return function(handler) ( return delgate(criteria, handler); ) );
    Αρχικό άρθρο: Κατανόηση των εκχωρημένων συμβάντων JavaScript
    (Από τον μεταφραστή: πρώτος μου, κρίνετε αυστηρά.)

    Καλή κωδικοποίηση!

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

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

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

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

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

    Ανάβαση

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

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

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

    σώμα * ( περιθώριο: 10 εικονοστοιχεία, περίγραμμα: 1 εικονοστοιχείο συμπαγές μπλε; ) FORM DIV

    Η φυσαλίδα εξασφαλίζει ότι το κλικ στο εσωτερικό στοιχείο

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

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

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

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

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

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

    Εν:

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

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

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

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

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

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

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

    Κάντε κλικ με

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

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

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

    Κατάδυση

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

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

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

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

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

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

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

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

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

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

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

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

    Ο κώδικας JS εδώ είναι:

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


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

    Var elems = 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 (=this) – το στοιχείο στο οποίο ενεργοποιείται αυτήν τη στιγμή ο self-handler (στο οποίο έχει «φθάσει» το συμβάν).
    • event.eventPhase – σε ποια φάση ενεργοποιήθηκε ο χειριστής συμβάντων (dive = 1, ascend = 3).

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