JavaScript core knowledge Chapter 2 - Advanced events (including a lot of code analysis)

Posted by djwiltsh on Sun, 06 Mar 2022 21:50:52 +0100

preface❤️ How much talent a person has, how much humility will be engraved in his bones ❤️

1, JavaScript event advanced

(1) Registration event (binding event)

1.1 overview of registration events

one ️⃣ Adding an event to an element is called a registration event or a binding event.
two ️⃣ There are two ways to register events: traditional method and method listening registration method;

1.2 addEventListener event listening method

eventTarget.addEventListener(type, listener[, useCapture])

eventTarget. The addeventlistener () method registers the specified listener with the EventTarget (target object). When the object triggers the specified event, the event handling function will be executed.

The method receives three parameters:

  • Type: event type string, such as click and mouseover. Note that there is no on here;
  • listener: event handling function, which will be called when an event occurs;
  • useCapture: optional parameter. It is a Boolean value. The default value is false;

1.3 attachEvent event listening method (just understand)

eventTarget.attachEvent(eventNameWithOn, callback)

eventTarget. The attachevent () method registers the specified listener with the EventTarget (target object). When the object triggers the specified event, the specified callback function will be executed.

The method receives two parameters:

  • eventNameWithOn: event type string, such as onclick and onmouseover, with on;
  • Callback: event handling function. When the target triggers an event, the callback function is called;

😆 Warm reminder 😆: IE8 and earlier versions support;

The code is shown as follows:

<body>
    <button>Traditional registration event</button>
    <button>Method listens for registration events</button>
    <button>ie9 attachEvent</button>
    <script>
        var btns = document.querySelectorAll('button');
        // 1. Traditional registration events
        btns[0].onclick = function() {
            alert('hi');
        }
        btns[0].onclick = function() {
                alert('hi DJ');
            }
            // 2. Event listener registers the event addEventListener 
            // (1) The event type inside is a string. It must be quoted without on
            // (2) Multiple listeners (event handlers) can be added to the same element and the same event
        btns[1].addEventListener('click', function() {
            alert(24);
        })
        btns[1].addEventListener('click', function() {
                alert(30);
            })
            // 3. attachEvent ie9 previous versions support
        btns[2].attachEvent('onclick', function() {
            alert(99);
        })
    </script>
</body>

1.4 registered event compatibility solution

The code is shown as follows:

 function addEventListener(element, eventName, fn) {
      // Judge whether the current browser supports the addEventListener method
      if (element.addEventListener) {
        element.addEventListener(eventName, fn);  // The third parameter defaults to false
      } else if (element.attachEvent) {
        element.attachEvent('on' + eventName, fn);
      } else {
        // Equivalent to element onclick = fn;
        element['on' + eventName] = fn;
 } 

😆 Principles of compatibility handling 😆: First take care of most browsers, and then deal with special browsers;

(2) Delete event (unbind event)

2.1 method of deleting events

one ️⃣ Traditional registration method

eventTarget.onclick = null;

two ️⃣ Method monitoring registration method

1. eventTarget.removeEventListener(type, listener[, useCapture]);
2. eventTarget.detachEvent(eventNameWithOn, callback);

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function () {
            alert(11);
            // 1. Delete events in traditional way
            divs[0].onclick = null;
        }
        // 2. removeEventListener delete event
        divs[1].addEventListener('click', fn) // fn inside does not need to be called with parentheses

        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }
        // 3. detachEvent
        divs[2].attachEvent('onclick', fn1);

        function fn1() {
            alert(33);
            divs[2].detachEvent('onclick', fn1);
        }
    </script>
</body>

</html>

2.2 delete event compatibility solution

The code is shown as follows:

 function removeEventListener(element, eventName, fn) {
      // Judge whether the current browser supports the removeEventListener method
      if (element.removeEventListener) {
        element.removeEventListener(eventName, fn);  // The third parameter defaults to false
      } else if (element.detachEvent) {
        element.detachEvent('on' + eventName, fn);
      } else {
        element['on' + eventName] = null;
 } 

(3) DOM event flow

one ️⃣ Event flow describes the order in which events are received from the page.
two ️⃣ When an event occurs, it will propagate between element nodes in a specific order. This propagation process is DOM event flow.

three ️⃣ DOM event flow is divided into three stages:

  1. Capture phase;
  2. Current target stage;
  3. Bubbling stage;
  • Event bubbling: IE first proposed that the event is received by the most specific element at the beginning, and then propagated up to the top node of DOM level by level;
  • Event capture: Netscape was first proposed, which starts from the top node of DOM, and then propagates down to the most specific element receiving process level by level;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .father {
            overflow: hidden;
            width: 300px;
            height: 300px;
            margin: 100px auto;
            background-color: pink;
            text-align: center;
        }
        
        .son {
            width: 200px;
            height: 200px;
            margin: 50px;
            background-color: purple;
            line-height: 200px;
            color: #fff;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">son Box</div>
    </div>
    <script>
        // dom event flow has three stages
        // 1. Only one stage of capture or bubbling can be executed in JS code.
        // 2. onclick and attachEvent (ie) can only get the bubbling stage.
        // 3. In the capture phase, if the third parameter of addEventListener is true, it is in the capture phase document - > HTML - > body - > father - > son
        // var son = document.querySelector('.son');
        // son.addEventListener('click', function() {
        //     alert('son');
        // }, true);
        // var father = document.querySelector('.father');
        // father.addEventListener('click', function() {
        //     alert('father');
        // }, true);
        // 4. In the bubbling stage, if the third parameter of addEventListener is false or omitted, it is in the bubbling stage son - > father - > body - > HTML - > document
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, false);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>

</html>

😆 Warm reminder 😆:

  1. Only one stage of capture or bubbling can be executed in JS code.
  2. onclick and attachEvent can only get the bubbling phase.
  3. addEventListener(type, listener[, useCapture]) if the third parameter is true, it means to call the event handler in the event capture phase; If it is false (the default is false if it is not written), it means that the event handler is called in the event bubbling stage.
  4. In actual development, we rarely use event capture, and we pay more attention to event bubbling.
  5. Some events do not bubble, such as onblur, onfocus, onmousenter, onmouselive.
  6. Event bubbling sometimes brings trouble, and sometimes helps to do some events skillfully. We'll explain later.

(4) Event object

4.1 what is the event object

eventTarget.onclick = function(event) {} 
eventTarget.addEventListener('click', function(event) {})
// This event is the event object. We also like to write it as e or evt 

one ️⃣ Official explanation: the event object represents the state of the event, such as the state of the keyboard keys, the position of the mouse, and the state of the mouse buttons.
two ️⃣ After the event is put into the object, there is a series of data related to the event.

For example:

  1. Who bound this event.
  2. If the mouse triggers an event, you will get the relevant information of the mouse, such as the mouse position.
  3. If the keyboard triggers an event, you will get the relevant information of the keyboard, such as which key you pressed.

4.2 usage syntax of event object

eventTarget.onclick = function(event) {
	// This event is the event object. We also like to write it as e or evt 
  } 
eventTarget.addEventListener('click', function(event) {
    // This event is the event object. We also like to write it as e or evt 
  })

This event is a formal parameter. The system helps us set it as an event object without passing an argument.
When we register an event, the event object will be automatically created by the system and passed to the event listener (event handler) in turn.

4.3 compatibility scheme of event object

There is a compatibility problem with the acquisition of the event object itself:

  1. In the standard browser, the parameters passed by the browser to the method can be obtained by defining the formal parameter e.
  2. In IE6~8, the browser will not pass parameters to the method. If necessary, it needs to go to window Get the lookup in event.

😆 solve 😆: e = e || window.event;

4.4 common attributes and methods of event objects

Event object attribute methodexplain
e.targetReturn the object that triggered the event   standard
e.srcElementReturn the object triggering the event   non standard ie6-8 use
e.typeReturn the type of event   such as click mouseover without on
e.canselBubbleThis attribute prevents bubbling   non-standard ie6-8 use
e.returnValueThis attribute prevents default events (default behavior)   non-standard ie6-8 use, such as not allowing links to jump
e.prevenDefault()This method prevents default events (default behavior)   standards, such as not allowing links to jump
e.stopPropagation()Anti foaming standard

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div>123</div>
    <a href="http://www.baidu. Com "> Baidu</a>
    <form action="http://www.baidu.com">
        <input type="submit" value="Submit" name="sub">
    </form>
    <script>
        // Properties and methods of common event objects
        // 1. Return event type
        var div = document.querySelector('div');
        div.addEventListener('click', fn);
        div.addEventListener('mouseover', fn);
        div.addEventListener('mouseout', fn);

        function fn(e) {
            console.log(e.type);

        }
        // 2. Block the default behavior (event) so that the link does not jump or the submit button does not submit
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom standard writing
            })
            // 3. Traditional registration methods
        a.onclick = function(e) {
            // Ordinary browser e.preventDefault(); method
            // e.preventDefault();
            // Lower browser ie678 returnValue property
            // e.returnValue;
            // We can also use return false to prevent the default behavior. There is no compatibility problem: the code behind return is not executed, and it is only limited to the traditional registration method
            return false;
            alert(11);
        }
    </script>
</body>

</html>

😆 e. The difference between target and this 😆:

  • This is the element bound to the event, and the caller of this function (the element bound to the event);
  • e.target is the element triggered by the event;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div>123</div>
    <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
        // Properties and methods of common event objects
        // 1. e.target returns the object (element) that triggered the event. this returns the object (element) that bound the event
        // Difference: if e.target clicks the element, it will return the element. If this element is bound to the click event, then who will be returned
        var div = document.querySelector('div');
        div.addEventListener('click', function (e) {
            console.log(e.target);
            console.log(this);

        })
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function (e) {
            // If we bind an event to ul, this points to ul  
            console.log(this);
            console.log(e.currentTarget);

            // e.target points to the object we clicked. Who triggered this event? We clicked li e.target points to li
            console.log(e.target);

        })
        // Understanding compatibility
        // div.onclick = function(e) {
        //     e = e || window.event;
        //     var target = e.target || e.srcElement;
        //     console.log(target);
        // }
        // 2. Understand that there is a very similar attribute to this. Currenttarget ie678 doesn't know
    </script>
</body>

</html>

(5) Prevent event bubbling

5.1 two ways to prevent event bubbling

Event bubbling: it is received by the most specific element at the beginning, and then propagated up to the top node of DOM level by level.
The characteristics of event bubbling will bring both disadvantages and benefits, which we need to master flexibly.

Prevent event bubbling:

  • Standard writing method: use the stopPropagation() method in the event object;
e.stopPropagation()
  • Non standard writing: IE 6-8 uses the cancelBubble attribute of the event object;
e.cancelBubble = true;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .father {
            overflow: hidden;
            width: 300px;
            height: 300px;
            margin: 100px auto;
            background-color: pink;
            text-align: center;
        }
        
        .son {
            width: 200px;
            height: 200px;
            margin: 50px;
            background-color: purple;
            line-height: 200px;
            color: #fff;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">son Son</div>
    </div>
    <script>
        // Properties and methods of common event objects
        // Stop bubbling dom recommended standard stopPropagation() 
        var son = document.querySelector('.son');
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation(); // Stop stop Propagation
            e.cancelBubble = true; // Non standard cancel bubble
        }, false);

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>

</html>

5.2 compatibility solutions to prevent event bubbling

The code is shown as follows:

if(e && e.stopPropagation){
	e.stopPropagation();
}else{
    window.event.cancelBubble = true;
}

(6) Event delegation (agency, delegation)

one ️⃣ Event delegation: event delegation is also called event proxy, which is called event delegation in jQuery.

two ️⃣ Principle of event delegation: instead of setting the event listener separately for each child node, the event listener is set on its parent node, and then the bubble principle is used to affect the setting of each child node ❗ ️ ❗ ️ ❗ ️

three ️⃣ Function of event delegation: DOM is operated only once, which improves the performance of the program.

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>I have three loves, the sun, the moon and you. The sun is the morning, the moon is the evening, and you are the morning and evening. --Bird collection</li>
        <li>I have three loves, the sun, the moon and you. The sun is the morning, the moon is the evening, and you are the morning and evening. --Bird collection</li>
        <li>I have three loves, the sun, the moon and you. The sun is the morning, the moon is the evening, and you are the morning and evening. --Bird collection</li>
        <li>I have three loves, the sun, the moon and you. The sun is the morning, the moon is the evening, and you are the morning and evening. --Bird collection</li>
        <li>I have three loves, the sun, the moon and you. The sun is the morning, the moon is the evening, and you are the morning and evening. --Bird collection</li>
    </ul>
    <script>
        // The core principle of event delegation: add a listener to the parent node and use event bubbling to affect each child node
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // alert('whether you know it or not, click I should have a bullet frame in hand! ');
            // e.target is the object we can click on
            e.target.style.backgroundColor = 'pink';
        })
    </script>
</body>

</html>

(7) Common mouse events

7.1 common mouse events

Mouse eventTrigger condition
onclickClick the left mouse button to trigger
onmouseoverMouse over trigger
onmouseoutMouse departure trigger
onfocusGet mouse focus trigger
onblurLoss of mouse focus trigger
onmousemoveMouse movement trigger
onmouseupMouse bounce trigger
onmousedownMouse press trigger

one ️⃣ Disable right mouse button menus
contextmenu mainly controls when the context menu should be displayed. It is mainly used by programmers to cancel the default context menu;

document.addEventListener('contextmenu', function(e) {
	e.preventDefault();
})

two ️⃣ Disable mouse selection (select Start starts selection)

document.addEventListener('selectstart', function(e) {
	e.preventDefault();
})

7.2 mouse event object

Event object represents the state of the event and a collection of a series of information related to the event.
At this stage, we mainly use mouse event object MouseEvent and keyboard event object KeyboardEvent.

Mouse event objectexplain
e.clientXReturns the X coordinate of the mouse relative to the viewable area of the browser window
e.clientXReturns the Y coordinate of the mouse relative to the viewable area of the browser window
e.pageXReturn the X coordinate of the mouse relative to the document page   IE9 + support
e.pageYReturn the Y coordinate of the mouse relative to the document page   IE9 + support
e.screenXReturns the X coordinate of the mouse relative to the computer screen
e.screenYReturns the Y coordinate of the mouse relative to the computer screen

(8) Common keyboard events

8.1 common keyboard events

Events can be triggered not only with the mouse, but also with the keyboard.

Keyboard eventsTrigger condition
onkeyupTriggered when a keyboard key is released
onkeydownTriggered when a keyboard key is pressed
onkeypressTriggered when a keyboard key is released, but it does not recognize the function key, such as ctrl shift arrow, etc

😆 Warm reminder 😆:

  1. If you use addEventListener, you do not need to add on;
  2. The difference between onkeypress and the previous two is that it does not recognize function keys, such as left and right arrows, shift, etc;
  3. The execution sequence of the three events is: keydown "keypress" keyup;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        // Common keyboard events
        //1. Triggered when the Keyup button pops up 
        document.addEventListener('keyup', function () {
            console.log('I bounced up');
        })

        //3. When the keypress key is pressed, the unrecognized function key is triggered, such as the left and right arrows of ctrl shift
        document.addEventListener('keypress', function () {
            console.log('I pressed press');
        })
        
        //2. When the Keydown key is pressed, it will trigger a function key that can be recognized, such as the left and right arrows of ctrl shift
        document.addEventListener('keydown', function () {
            console.log('I pressed down');
        })
            // 4. Execution sequence of three events keydown -- keypress -- keyup
    </script>
</body>

</html>

8.2 keyboard event object

Keyboard event object propertiesexplain
keyCodeReturns the ASCII value of the key

😆 Warm reminder 😆:

  • onkeydown and onkeyup are case insensitive, and onkeypress is case sensitive;
  • In our actual development, we use keydown and keyup more, which can identify all keys (including function keys);
  • Keypress does not recognize function keys, but the keyCode attribute is case sensitive and returns different ASCII values;

The code is shown as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        // The ASCII code value of the corresponding key can be obtained from the keyCode attribute in the keyboard event object
        // 1. Our keyup and keydown events are not case sensitive. Both A and A get 65
        // 2. Our keypress event is case sensitive. A 97 and a get 65
        document.addEventListener('keyup', function(e) {
            // console.log(e);
            console.log('up:' + e.keyCode);
            // We can use the ASCII code value returned by keycode to judge which key the user pressed
            if (e.keyCode === 65) {
                alert('You pressed a key');
            } else {
                alert('You didn't press a key')
            }
        })
        document.addEventListener('keypress', function(e) {
            // console.log(e);
            console.log('press:' + e.keyCode);
        })
    </script>
</body>

</html>
8.2.1 case: simulate JD key input content

Requirements: when we press the s key, the cursor will be positioned to the search box;

Case study:

  1. Core idea: check whether the user presses the s key. If the user presses the s key, the cursor will be positioned in the search box;
  2. Use the keyCode in the keyboard event object to judge whether the user pressed the s key;
  3. Search box to get focus: use the focus() method in js;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <input type="text">
    <script>
        var search = document.querySelector('input');
        document.addEventListener('keyup', function(e) {
            // console.log(e.keyCode);
            if (e.keyCode === 83) {
                search.focus();
            }
        })
    </script>
</body>

</html>
8.2.2 case: simulate JD express order No. query

Requirements: when we enter the content in the text box, the large font content will be automatically displayed on the text box;

Case study:

  1. When inputting the contents of the express order number, the text in the text box will be displayed in the large font box (con) above;
  2. At the same time, the value in the express order number is obtained and assigned to the con box (innerText) as the content;
  3. If the content in the express order number is empty, the large font box (con) box will be hidden;
  4. Note: the characteristics of keydown and keypress in the text box: when their two events are triggered, the text has not fallen into the text box. When the keyup event is triggered, the text has fallen into the text box;
  5. When we lose focus, we hide the con box;
  6. When we get the focus and the content of the text box is not empty, the con box is displayed;

The complete code is demonstrated as follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .search {
            position: relative;
            width: 178px;
            margin: 100px;
        }
        
        .con {
            display: none;
            position: absolute;
            top: -40px;
            width: 171px;
            border: 1px solid rgba(0, 0, 0, .2);
            box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
            padding: 5px 0;
            font-size: 18px;
            line-height: 20px;
            color: #333;
        }
        
        .con::before {
            content: '';
            width: 0;
            height: 0;
            position: absolute;
            top: 28px;
            left: 18px;
            border: 8px solid #000;
            border-style: solid dashed dashed;
            border-color: #fff transparent transparent;
        }
    </style>
</head>

<body>
    <div class="search">
        <div class="con">123</div>
        <input type="text" placeholder="Please enter your courier number" class="jd">
    </div>
    <script>
        // When you enter the content of the express order number, the large font box (con) above will display (the font size inside is larger)
        // Form detection user input: add keyboard events to the form
        // At the same time, get the value in the express order number and assign it to the con box (innerText) as the content
        // If the content in the express order number is empty, the large font box (con) box will be hidden
        var con = document.querySelector('.con');
        var jd_input = document.querySelector('.jd');
        jd_input.addEventListener('keyup', function() {
                // console.log('input content ');
                if (this.value == '') {
                    con.style.display = 'none';
                } else {
                    con.style.display = 'block';
                    con.innerText = this.value;
                }
            })
            // When we lose focus, we hide the con box
        jd_input.addEventListener('blur', function() {
                con.style.display = 'none';
            })
            // When we get the focus, the con box is displayed
        jd_input.addEventListener('focus', function() {
            if (this.value !== '') {
                con.style.display = 'block';
            }
        })
    </script>
</body>

2, Summary

😝 Because there are many contents, I decided to write separately. I will keep updating! Like friends, remember to praise! 😝

Topics: Javascript Front-end Programming ECMAScript