Event (1)

event

The interaction between js and html is done through events; events are some specific interactive moments that occur in documents or browser windows.

Event Streaming (Event Propagation)

During the development of the browser, the development team encountered a problem. That is which part of the page has a specific event?

You can imagine a set of concentric circles drawn on a piece of paper. If you put your finger on the center of the circle, then your finger is not actually pointing to a circle, but all the circles on the paper. Both iE and Netscape support the view that if a button is clicked, the click event occurs not only on the button, but even on the entire page (all parent elements of the button are clicked).

The question for the development team is, when the button is clicked, is the button's outermost parent element first to receive the event and execute it, or is the specific element first to receive the event and execute it? So the concept of event flow is introduced here.

Event Flow: Describes the order in which events are received by the page.

But the two companies come up with completely opposite event streaming schemes (considering the way events are propagated differently). IE supports event bubbling streams , and Netscape supports event capture streams .

event bubbling

Event bubbling: The event is defined as being triggered (received) from the most specific element (the element clicked at the time), and then propagated upwards to less specific elements (document document)

<html>
<head>
  <meta charset="UTF-8">
  <title>事件</title>
</head>
<body>
  <div id="myDiv">Click Me</div>
</body>
</html>

After clicking the div element in the page, the click event will occur in the following order:
div->body->html->document
That is to say, the clicked element first triggers the click event, and then goes all the way up the DOM tree, after passing Triggered on each node in turn until the document object is reached.

Note: All browsers support event bubbling, and it will always bubble up to the window object (some versions before IE9 only bubble up to document), but there will be some changes in the way of implementation.

event capture

Event capture: events should be received first by less specific nodes, and should be received last by the most specific nodes. Event capture is actually to intercept events before they reach their final destination.

<html>
<head>
  <meta charset="UTF-8">
  <title>事件</title>
</head>
<body>
  <div id="myDiv">Click Me</div>
</body>
</html>

In the same example, when using event capture, the trigger sequence is:
document->html->body->div

stages of event flow

  1. Event capture phase: When an element triggers an event, the top-level object document will send out an event stream, following the nodes of the DOM tree like the target element node until it reaches the target element where the event actually occurs.
  2. In the target stage: When the target element is reached, the corresponding processing function of the event of the target element is executed.
    Then, the bubbling phase occurs and events start bubbling.
  3. Event bubbling stage: starting from the target element and propagating to the top element, if there are nodes on the way bound to the corresponding event processing functions, these functions will be triggered in turn

insert image description here
Event capture occurs first, making it possible to intercept events in advance. Then, the actual target element receives the event (reaching the target stage), and the last stage is bubbling, which is the latest to respond to the event.

event handler

Event handler: The function called in response to an event is called an event handler, and the event handler starts with on, so the handler for the click event is called onclick, and the handler for the load event is called onload

HTML event handler

HTML event handler: write js directly on the HTML tag, which is the global scope.

<input type="button" value="Click Me" onclick="console.log('Clicked')">

When we need to use a complex function, it is obviously inappropriate to write the js code in it, so we have the following writing method (of course, it can also be defined in an external file and then imported):

<input type="button" value="Click Me" onclick="showMessage()">
  <script>
    function showMessage(){
    
    
      console.log("Hello world");
    }
  </script>

This will cause a time difference problem. It is possible that the HTML element has been displayed on the page and the user has already interacted with it, but the code of the time handler cannot be executed. For example, in the above example, if the showMessage() function is behind the page, in the button Defined later in the code, if the button is clicked before the showMessage() function is defined, an error will be reported at this time. But we can wrap the function in a try-catch block to handle it:

<input type="button" value="Click Me" onclick="try{showMessage();}catch(e) {}">

In this way, if the button is clicked before the showMessage() function is defined, no JavaScript error will occur, because the error has been intercepted before the browser receives it.

At the same time, the change of a function may involve the modification of html and js at the same time, which is very inconvenient. Moreover, for different browsers, there are differences in the rules of identifier parsing in different JavaScript engines, so it cannot Accessing unqualified object members can lead to errors. In summary, we have DOM0 level event handlers.

shortcoming:

  1. Error if the page is not fully loaded.
  2. HTML is tightly coupled to JS.
  3. Different browsers show differences.

DOM0 level event handler

DOM0-level event handler: It is a traditional way to specify an event handler through js, which is to assign a function to an event handler attribute of a DOM element. (Each element has usually lowercased event handler attributes like onclick)

<body>
  <div id="box"></div>
  <script type="text/javascript">
    // 这种绑定方式只发生在事件的冒泡阶段
    let box = document.getElementById('box');
    box.onclick = function () {
    
    
      this.innerHTML += 1;
    }
  </script>
</body>

Notice:

  • The phase that occurs with DOM0-level event handlers is the bubbling phase of the event
  • When using the DOM0 method to assign values ​​to the event handler like this, the assigned function is regarded as a method of the element, so the event handler will run in the scope of the element, that is, this is equal to the element.

Remove event handler:

It can be seen from the code that the event handler onclick is bound to the box object, which means that the event handler is always referenced by the box object. If the page is not closed, the event handler will always be in memory, so when will the Will it be destroyed? Only when the page is closed will it be destroyed by the garbage collection mechanism in js. If you want to stop the event in the middle, then use the following method.

<body>
  <div id="box"></div>
  <script type="text/javascript">
    // 这种绑定方式只发生在事件的冒泡阶段
    let box = document.getElementById('box');
    box.onclick = function () {
    
    
      this.innerHTML += 1;
    }
    // 删除事件处理程序
    box.onclick = null;
  </script>
</body>

Compared with HTML, DOM0 level has two advantages:

  1. Simple
  2. Cross-browser advantage (supported by all browsers)

Disadvantage: The same time handler cannot be bound to the same element, if bound, there will be coverage

<body>
  <div id="box"></div>
  <script type="text/javascript">
    // 这种绑定方式只发生在事件的冒泡阶段
    let box = document.getElementById('box');
    box.onclick = function () {
    
    
      box.innerHTML += 1;
    }
    box.onclick = function (){
    
    
      this.innerHTML += 2;
   }
  </script>
</body>

DOM2 level event handlers

DOM2-level events define two methods for the assignment and removal of event handlers: addEventListener and removeEventListener.

addEventListener&&removeEventListener

addEventListener: Assignment of event handler
removeEventListener: Removal of event handler

These two methods are exposed on all DOM nodes and accept three parameters: event name (excluding on), event handler function and a Boolean value (true means to call the event handler during the capture phase, false (default value) means to The bubbling phase calls the event handler)

Assignment of event handlers

<body>
  <div id="box"></div>
  <script type="text/javascript">
    //addEventListener(事件名,处理程序的函数,布尔值)
    let box = document.getElementById('box');
    box.addEventListener('click',function () {
    
    
        this.innerHTML += 1;
    },false);
    box.addEventListener('click',function () {
    
    
        this.innerHTML += 2;
    },false)
  </script>
</body>

Event handler function passing parameters:

What if you want to pass a parameter to the event handler? It can be seen that the event processing function accepted in these two methods is an anonymous function. At this time, an anonymous function can be used to wrap a listening function

<body>
  <div id="box"></div>
  <script type="text/javascript">
    //给事件处理函数传递一个参数:使用匿名函数来包装一个监听函数
    box.addEventListener('click',function () {
    
    
      test(3)
    },false)
    function test(x){
    
    
      alert(x)
    }
  </script>
</body>

Note: IE8 browser does not support DOM2 level event handlers

event handler removal

Event handlers added via addEventListener() can only be removed using removeEventListener() and passing in the same parameters that were added, which means that anonymous functions added using addEventListener() cannot be removed.

The removeEventListener() method is used to remove the event handler added by the addEventListener() method. If the event handler is to be removed, the implementation of addEventListener() must use an external function. The handle is how to trigger this event, for example: a form element loses focus. Then the handle of this event is onBlur(), (also known as event handler)

<body>
  <div id="box"></div>
  <script type="text/javascript">
  let box = document.getElementById('box');
    //无效的方式
    //box.removeEventListener('click',function () {
    
    
    //   this.innerHTML += 1;
    //})

    //正确的移除事件的方式
    function handler() {
    
    
      this.innerHTML +=1;
    }
    box.addEventListener('click',handler,false)
    box.removeEventListener('click',handler,false)
  </script>
</body>

In most cases, event handlers are added to the bubbling phase of the event stream, mainly for cross-browser compatibility. Registering event handlers with the capture phase is typically used to intercept events before they reach their specified target.

Advantages : Compared with DOM0 level, DOM2 level event handlers can add multiple event handlers at the same time.

IE event handler

In IE, there is only the bubbling flow of events, and there is no stage of event capture

attachEvent&&detachEvent

Accepts two parameters: the name of the event handler and the event handler function . Because IE browser only supports event bubbling, the event handler added using attachEvent will be added to the event bubbling phase

Assignment of event handlers

<body>
  <div id="box"></div>
  <script type="text/javascript">
    let box = document.getElementById('box');
    box.attachEvent('onclick',function () {
    
    
    //没有使用this,而是直接指定的具体元素,如果使用this,打印出来为window对象
        box.innerHTML += 1;
    },false);
    box.attachEvent('onclick',function () {
    
    
        box.innerHTML += 2;
    },false)
  </script>
</body>

Notice:

  1. The above code results in 12 in IE9, IE10, and 21 in IE8. Because in IE9 and IE10, this method is executed sequentially, but in IE8 this method is executed in reverse order.
  2. The main difference between using attachEvent() and DOM0-level event handlers in Internet Explorer is the scope aspect. The scope of the DOM0-level event handler is on the current element , while the attachEvent is the global scope , which means that tihs points to the window.

event handler removal

Using attachEvent has the same problem as DOM2. If the function is written in it, the event listening function cannot be canceled.

<body>
  <div id="box"></div>
  <script type="text/javascript">
  	let box = document.getElementById('box');   
   	function handler() {
    
    
      this.innerHTML +=1;
    }
    //注意:on开口的是事件处理程序名
    box.attachEvent('onclick',handler)
    box.detachEvent('onclick',handler,false)
  </script>
</body>

Cross-Browser Event Handlers

To sum up, if we want to bind events and remove events, and there is no event coverage phenomenon, DOM2 level events are generally used at this time. The addEventListener method provided in the DOM2-level event program does not support IE8, so IE provides the attachEvent method for compatibility. The this inside attachEvent() points to the window, so we need to be compatible with the pointing of this.

this points to the question:

Case 1:

 function fn(){
    
    
      //指向window,打印结果:window
      console.log(this);
    }
 fn();

 //默认全局下的this也指向window,打印结果:window
 console.log(this)

Case two:

let obj = {
    
    
      name: 'zhangsan'
    }
    function fn(){
    
    
      //this指向window,打印结果:undefined
      console.log(this.name);
    }
    fn();

Case three:

fn() is equivalent to the abbreviation of fn.call(), but the call method can pass parameters, and the first parameter can specify the current direction of this. That is to say, the call method can change this to point to the problem.

 let obj = {
    
    
      name: 'zhangsan'
    }
    function fn(){
    
    
      //this指向obj,打印结果:zhangsan
      console.log(this.name);
    }
    fn.call(obj);

Compatible with all browsers

Not compatible with this in IE browser: IE8 prints out undefine, because this points to window

<body>
  <button id="btn">按钮</button>
  <script type="text/javascript">
    let btn = document.getElementById('btn');
    addEvent(btn,'Click',function () {
    
    
      //chrome firefox safari ie8以上(不包括IE8)打印出来为‘按钮’
      //IE8打印出来undefine,因为this指向的是window
      console.log(this.innerHTML)
    })
    
    //没有兼容IE浏览器中的this
    function addEvent(target,eventType,handler) {
    
    
       if(target.addEventListener){
    
    
         //chrome firefox safari ie8以上(不包括IE8)
         target.addEventListener(eventType,handler,false);
       }else{
    
    
         target.attachEvent('on' + eventType,handler)
       }
    }
  </script>
</body>

Compatible with iE browser this (compatibility code for full browser event handler)

<body>
  <button id="btn">按钮</button>
  <script type="text/javascript">
    let btn = document.getElementById('btn');
    addEvent(btn,'Click',function () {
    
    
      //chrome firefox safari ie8以上(不包括IE8)打印出来为‘按钮’
      //IE8打印出来undefine,因为this指向的是window
      console.log(this.innerHTML)
    })
    
     //兼容iE浏览器的this(全浏览器事件处理程序的兼容性代码)
    function addEvent(target,eventType,handler) {
    
    
      if(target.addEventListener){
    
    
        //chrome firefox safari ie8以上(不包括IE8)
        target.addEventListener(eventType,handler,false);
      }else{
    
    
        target.attachEvent('on' + eventType,function(){
    
    
          handler.call(target);
        })
      }
    }
  </script>
</body>

Summary of event call sequence

<body>
    <!--html事件处理程序-->
  <div id="box" onclick="this.innerHTML += 'html\n'"></div>
  <script type="text/javascript">
    let box = document.getElementById('box');
    // DOM0级事件处理程序
    box.onclick = function () {
    
    
        this.innerHTML += 'DOM0级\n'
    }
    // DOM2级事件处理程序
    if (box.addEventListener) {
    
    
      box.addEventListener('click',function() {
    
    
        this.innerHTML += 'DOM2级\n'
      })
    }
    //IE事件处理程序
    if (box.attachEvent) {
    
    
      box.attachEvent('click',function() {
    
    
        this.innerHTML += 'IE\n'
      })
    }
  </script>
</body>
  1. If an HTML event handler and a DOM0-level event handler are present at the same time, the DOM0-level event handler will override the HTML event handler
  2. chrome, safari, firefox and IE11 result: DOM0 level DOM2 level
  3. IE9, 10 result is DOM0 level, DOM2 level, IE
  4. IE8 result: DOM0 level, IE

Guess you like

Origin blog.csdn.net/weixin_48242257/article/details/120550012