1. Event model

  • We know that the DOM is a tree structure, so when we click a button on the page, which elements on the page trigger the event, do they happen on the button, or do the button’s container elements (we say the parent elements) also trigger the click event? So this is the event stream, and after thinking about it, we know that it describes the order in which the events fire, does it fire both the button and its container elements, which one of them fires first? This is not certain, depending on the type of event flow.

  • Let’s think about it through a model

  • From the figure we can see the three phases in the event model (executed in sequence)

1.Capture phase2.The target stage3.Bubbling phaseCopy the code

2. Event binding API

<div class="a"> <div class="b"> text </div> </div> a.deventListener ('click',fn,bool)Copy the code

Fn is a function. If bool is not passed or the value falsy, fn will bubble. That is, when the browser finds that A has fn listener function in the bubbling phase, fn will be called and event information will be provided. If bool is true, let fn capture, that is, when the browser detects that A has a FN listener during the capture phase, fn will be called and event information will be provided.

Precautions If you listen directly, you cannot listen to events. After 1s, events are finished. Therefore, you need to record the monitored events

3. The target and currentTarget

Target is the element on which the user operates, and currentTarget is the element on which the programmer listens. For example:

<div> <span> text </span> </div> //e.target is span // e.currenttarget is divCopy the code

4. How to cancel bubbling

Note that capture is not cancelable, but bubbling is

e.stopPropagation()// Can interrupt bubbling, generally used to encapsulate some independent components
Copy the code

5. Customize events

<div> <button id="button1"></button> </div> button1.addElementListener('click',()=>{ const event = new CustomEvent('huo',{detail:{name:'huo',age:2}}) The event name and event information for the dispatchEvent (event). / / the event triggered}) for the addElementListener (' re-arrest -- '(e) = > {the console. The log (e.d etail) / / to monitor this event })Copy the code

6. Event delegation

Event delegate is to listen for the ancestor element, and when we click it, we will determine whether it is the element we want to listen for. If it is, we will execute the function. The advantage of event delegate is that it saves memory and can listen for dynamic elements.

Event encapsulation is as follows:

function on(eventType,element,selector,fn){
if(! (element instance Element)){ element =document.querySelector(element) // If element is not an element, go to that element
}
    element.addEventListener(eventType,()=>{
    const t = e.target  //t is equal to the element being manipulated
    if(t.matches(selector)){   // If t matches selector,
        fn(e)
    }
    })
}

on('click'.'#div'.'butotn', () = > {console.log("Btton was clicked.")})Copy the code

There is a problem with the above code if the target is not necessarily the one we are listening for, so we need to use recursion to fix this.

function on(eventType,element,selector,fn){
    if(! (elementinstanceof Element)){
        element = document.querySelector(element)
    }
    
    element.addEventListener(eventType,(e)=>{
        let t = e.target
        while(t.tagName.toLowercase() ! == selector){if(t === element){
                t = null
                break
            }
            t = t.parentNode
        }
        t && fn.call(t,e,t)
    })
    return element
}Copy the code