The event model

Event propagation

  • Event capture

The capture stages are window, Document, HTML, body, div and button

  • Bubbling phase

Button, div, body, HTML, document, window

The impact of CSS on event propagation

  1. Event propagation between parent and child DOM elements is unaffected by CSS and depends only on the DOM tree
<div id="outer" style="height:10px; background-color: red;">
    <button id="inner1" style="position: absolute; top: 20px">Click on the</button>
</div>
Copy the code

  1. The cascading relationship between sibling nodes affects the triggering of events
<div id="outer" style="height:10px; background-color: red;">
        <button id="inner1" style="position: absolute; top: 20px">Click on the</button>
        <button style="position: absolute; top: 20px">cover</button>
    </div>
Copy the code

The solution is to add pointer-Event: None to the CSS attribute of the mask element so that it cannot be the target node of the event

 <button style="position: absolute; top: 20px; pointer-events: none;">cover</button>
Copy the code

The event agent

Due to the property of event bubbling, event listeners are not bound to all child nodes, but only to the parent element. The lowest DOM element of event bubbling can be determined by the target attribute of the event object

<body>
    <div id="outer">
        <button id="inner1">Click on the</button>
        <button id="inner2">Click on the</button>
    </div>
    <script>
        document.getElementById('outer').addEventListener('click', outterClick)
        document.getElementById('inner1').addEventListener('click', inner1Click)
        document.getElementById('inner2').addEventListener('click', inner2Click)

        function outterClick(e) {
            console.log('outter', e.target, this, e.target === this) // false
        }

        function inner1Click(e) {
            console.log('inner1', e.target, this, e.target === this) // true
        }

        function inner2Click(e) {
            console.log('inner2', e.target, this, e.target === this)}</script>
</body>
Copy the code

E.currenttarget should be this(the current DOM element), but when testing bull

Preventing an event from spreading

e.stopPropagation()

<body>
    <div id="outer">
        <button id="inner1">Click on the</button>
    </div>
    <script>
        document.getElementById('outer').addEventListener('click', outterClickDown, true)
        document.getElementById('outer').addEventListener('click', outterClickUp)
        document.getElementById('inner1').addEventListener('click', innerClickDown, true)
        document.getElementById('inner1').addEventListener('click', innerClickUp)

        function outterClickDown(e) {
            console.log('outterDown', e.target, this, e.target === this)}function innerClickDown(e) {
            console.log('innerDown', e.target, this, e.target === this)}function innerClickUp(e) {
            event.stopPropagation();

            console.log('innerUp', e.target, this, e.target === this)}function outterClickUp(e) {
            console.log('outterUp', e.target, this, e.target === this)}</script>
</body>
Copy the code

Pay attention to

  1. This method only prevents events from propagating backwards, and functions of the current stage on the current element will still be fired by the event (for example, if multiple functions are bound).
  2. At the deepest level of the DOM, the bubbling phase function is always fired, whether the capture phase or the bubbling phase calls this method
  3. To switch to e.s topImmediatePropagation () can change the above two results

Bind three methods of event listening

  1. HTML attributes:

Note that you do not write parentheses for function calls in React, but you do write parentheses in native HTML. Using this method the function is fired only during the event bubble phase

<body>
   <div onclick="myclick()">
       <button onclick="console.log(1)">Click on the</button>
   </div>
   <script>
       function myclick() {
           console.log('2')}</script>
</body>
Copy the code

The above effect is equivalent to element.setattribute ()

<body>
    <div id="outer">
        <button onclick="console.log(1)">Click on the</button>
    </div>
    <script>
        document.getElementById('outer').setAttribute('onclick'.'myclick()')

        function myclick() {
            console.log('2')}</script>
</body>
Copy the code
  1. Event attributes of DOM elements
<body>
    <div id="outer">
        <button onclick="console.log(1)">Click on the</button>
    </div>
    <script>
        document.getElementById('outer').onclick = myclick
        function myclick() {
            console.log('2')}</script>
</body>
Copy the code

Note that the value of onclick is a function object without parentheses.

In this approach, listeners can only be fired during the event bubble phase.

  1. The dom element addEventListener
<body>
    <div id="outer">
        <button onclick="console.log(1)">Click on the</button>
    </div>
    <script>
        document.getElementById('outer').addEventListener('click', myclick, true)
        function myclick() {
            console.log('2')}</script>
</body>
Copy the code

AddEventListener takes three arguments, the event name, the function name, and a Boolean value.

The last Boolean indicates whether the function will be fired during the event capture phase or event bubbling phase, true for capture phase, false for bubbling phase, and false by default.

Event capture and event bubbling

Common event

The mouse moves

  • Mouseenter: Triggered when the mouse moves over an element. (No bubbles)
  • Mouseleave: Triggered when the mouse moves over an element. (No bubbles)
  • Mouseover: Triggered when the mouse moves over an element, as well as moving in and out of its children.
  • Mouseout: Triggered when the mouse moves out of an element, as well as moving in and out of its children.
  • Mousemove: Fires when the mouse moves over an element, even on its children.
<! DOCTYPEhtml>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .a {
            width: 300px;
            height: 300px;
            background: rgb(149.206.255);
        }

        .b {
            width: 200px;
            height: 200px;
            background: beige;
        }

        .c {
            width: 100px;
            height: 100px;
            background: violet;
        }
    </style>
</head>

<body>
    <div class="a">A
        <div class="b" onmouseenter="mouseenter()" onmouseleave="mouseleave()" onmouseout="mouseout()"
            onmouseover="mouseover()" onmousemove="mousemove()">B
            <div class="c">C
            </div>
        </div>
    </div>
    <script>
        function mouseenter() {
            // console.log('mouseenter')
        }

        function mouseleave() {
            // console.log('mouseleave')
        }

        function mouseout() {
            // console.log('mouseout')
        }

        function mouseover() {
            console.log('mouseover')}function mousemove() {
            // console.log('mousemove')
        }
    </script>
</body>

</html>
Copy the code

Mobile event

Unique touchstart/touchmove/touchend/touchcancacel

Also has Click

Tap/Swipe, however, is not a native mobile event and is wrapped around a Touch event

Click on the delay

Click on mobile is 300ms slower than click on TouchStart/PC, since double clicking is a magnification operation that is buffeted against click events

Click through

The event is not dom generated, but browser-issued, and due to click delay, another click event is issued 300ms after a touchstart

Suppose there are two elements A and B on the page. B is on top of A. We registered a callback function on the touchStart event of the B element, which hides the B element. We find that when we click on the B element, the B element is hidden, and then the A element fires the click event.