Introduction:

For the following code

< div class = "grandpa" > < div class = "dad" > < div class = "son" > text < / div > < / div > < / div >Copy the code
  • At the same time, we added event listener fn1, fn2 and fn3 to grandpa div, dad div and son div respectively

Question 1:

  • Click on the text, calculate not click son?

  • Click on the text, does that count as clicking dad?

  • Click text, does it count as click grandpa?

Answer: Both

Question 2:

  • Click on the text to call fn1, fn2, or fn3 first?

  • The answer is either, if it’s a capture mechanism, call FN1 from the outside in first

  • If it’s bubbling, it works from the inside out, that is, calling FN3 first

  • Let’s take a closer look at DOM event mechanisms and event delegates

DOM event mechanism

The DOM event mechanism mainly consists of two phases: capture phase and bubbling phase

1. What is capture and bubbling?

  • When an event occurs on an element that has a parent element, modern browsers run two different phases – the capture phase and the bubble phase.

In the capture phase:

  • The browser checks the outermost ancestor of the element<html>, whether one was registered during the capture phaseonclickEvent handler, if so, run it.
  • And then, it moves to<html>Click on the element’s next ancestor and do the same, then click on the element and the next ancestor, and so on until you reach the actual clicked element.

In the bubbling stage:

  • The browser first checks the clicked element (in the initial example, text), then sees if there is an Onclick event in the bubble phase, and if so, runs it

  • Then, look for the next parentNode (in the initial example, the son div) and see if there is an Onclick event in the bubble phase, if so, run it

  • Then find the next ParentNode (in our example, the dad div).

  • When we use addEventListener to listen for events, addEventListener(‘click’, fn, bool)

  • If the third parameter bool is not passed, or false is passed, then fn is called during the bubble phase

  • If the third parameter Bool is passed true, then fn is called during the capture phase

2.W3C event model

  • Capture (first father => Son) then bubble (second son => Father)
  • Note that the e object is passed to all listener functions
  • The e object does not exist after the event

Code practice

  • Write 14 blocks of code, first capture again bubble: js.jirengu.com/leheheteti/…

3. Cancel bubbling

  • Capture cannot be cancelled, but bubbling can be cancelled. This can be broken using e.topPropagation (), and the browser will not go up. If someone hits me, I’ll take care of it myself. Don’t tell my father. Js.jirengu.com/delufixewi/…

  • Generally used to encapsulate some independent components

  • However, some events cannot be cancelled, such as scroll event, which can be queried on MDN

4. Difference between Target and currentTarget

  • E.target The element that the user is working on

  • E.currenttarget The element that the programmer is listening on, this can be used (not recommended)

For example:

<span> Text </span> </div>Copy the code
  • Let’s say we’re listening for div, but the user is actually clicking on text, then

E.target is the SPAN tag

E.currenttarget is the div tag

4. Summary capture and bubbling:

  • Capture: When the user clicks a button, the browser traverses the window from top to bottom, triggering event handlers one by one.

  • Bubbling: The browser traverses the window from the bottom up to the button clicked by the user, triggering event handlers one by one.

Event delegation

1. What is event delegation

  • Because of the bubble phase, the browser iterates from the bottom up to the window, triggering event handlers one by one,

  • Therefore, it is possible to listen on an ancestor node (such as a parent node or a grandparent node) to process events of multiple children at the same time

2. Common application scenarios

  • Scene 1:

We want to add click events to 100 buttons, what do we do?

Stupidest way: just give 100 buttons all addeventListeners

With event delegate: The dad listens for the 100 buttons and, while bubbling, decides if Target is one of the 100 buttons

  • Scene 2:

We want to listen for click events for elements that do not currently exist. What do we do?

There’s event delegate: Listen for ancestors, wait until bubbles up, and decide if the element I clicked on is the one I want to listen for

So the advantage of using event delegates is that

1. The number of listeners can be saved to save memory

2. You can listen for dynamic elements

3. Code implementation

  • Need: listen for all li tags, console.log if the user clicked on li (‘ user clicked on li ‘)
<ul id="test">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>
Copy the code
  • So the JS code implemented is:
Ul# test test.addEventListener('click', (e)=> { If (t.matches(' Li ') {console.log(' user clicked on Li ')}})Copy the code
  • The implementation idea is simple

1. Listen on the parent element first

2. Then retrieve the current clicked element based on the event information sent in by the browser

3. Check if the current clicked element is li. If so, console.log(‘ user clicked on the li tag ‘)

Based on this, we can encapsulate an event delegate function

On ('click', '#test', 'li', ()=>{console.log(' user clicked li')}) function on(eventType, parentElement, selector, Fn) {// If it is an element, then it is an element, because only element can listen for the event if (! (parentElement instanceof Element)) { parentElement = parentElement.querySelectorAll(parentElement) } parentElement.addEventListener(eventType, (e)=>{ let target = e.target if (target.matches(selector)) { fn(e) } }) }Copy the code
  • But there is a small problem with this implementation. What if the clicked element has more than one parent?
<ul id="test">
	<li>
		<p>
      <span>1</span>
    </p>
	</li>
	<li>
		<p>
      <span>2</span>
    </p>
	</li>
	<li>
		<p>
      <span>3</span>
    </p>
	</li>
	<li>
		<p>
      <span>4</span>
    </p>
	</li>
</ul>
Copy the code
  • What we need to do is:

  • I recursively go up several levels of the parent node until I find the LI tag,

  • You must also limit the search to no more than parentElement,

  • In the example above, you should not go beyond the UL tag to look for the body tag

On ('click', '#test', 'li', ()=>{console.log(' console.log ')}) function on(eventType, element, selector, fn) {if (! (element instanceof Element)) { element = document.querySelectorAll(element) } element.addEventListener(eventType, (e)=>{let target = e.target // Break out of the loop if a selector matches while(! Target. Matches (selector)){if (target === element){ Call (target, e)} target &&fn. Call (target, e)})}Copy the code

conclusion

1. Summary capture and bubbling:

Capture: When the user clicks a button, the browser traverses the window from top to bottom, triggering event handlers one by one.

Bubble: The browser clicks a button from the userFrom down to upTraverse to the window, firing event handlers one by one.

2. What is event delegation

Definition: Listen for an ancestor element, thus listening for one and operating on multiple descendants at the same time

  • Because of the bubble phase, the browser iterates from the bottom up to the window, triggering event handlers one by one,

  • Therefore, it is possible to listen on an ancestor node (such as a parent node or a grandparent node) to process events of multiple children at the same time