Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
The event
JavaScript interacts with HTML through events that represent a meaningful moment in a document or browser window.
Listeners subscribe to events that are executed when an event occurs, separating the behavior of the page (defined in JavaScript) from the presentation of the page (defined in HTML and CSS).
π Supplementary history:
Events first appeared in Internet Explorer 3 and Netscape Navigator2, where they were intended to shift some form processing from the server to the browser. By the time Internet Explorer 4 and Netscape Navigator 3 were released, both browsers offered similar but different apis that lasted for generations. DOM2 began to attempt to standardize DOM event apis in a logical way. All modern browsers currently implement the core of DOM2 Events.
Flow of events
IE
ε Netscape
During the development of the fourth generation of Web browsers, the browser events had diverged.
Which part of the page has a particular event?
When you click on a button, you actually unlight the button and click on its container and the entire page.
The event stream describes the order in which the page receives events.
π Supplementary history:
The IE and Netscape development teams came up with almost opposite event flow scenarios.
IE will support event bubbling streams, while Netscape will support event capture streams.
The event bubbling
The IE event stream is called event bubbling.
Events are defined to start with the most specific element (the deepest node in the document tree) and propagate up to the less specific element (the document).
Early versions of Internet Explorer 5.5 skip HTML elements (from body straight to document). Events in modern browsers bubble up all the way to the Window object.
Event capture
The Netscape team has come up with another event stream called event capture.
Event capture means that the least specific node should receive the event first, and the most specific node should receive the event last. Event capture is really about intercepting events before they reach their final destination.
Today’s browsers capture Events from the Window object, whereas the DOM2 Events specification dictates that they start with a Document.
The DOM event flow
The DOM2 Events specification specifies that the event flow is divided into three phases: event capture, arrival to target, and event bubbling.
Event capture occurs first, making it possible to intercept events ahead of time. The actual target element then receives the event. The last stage is bubbling, and events must be responded to at the latest.
In the DOM event flow, the actual target (div element) does not receive the event during the capture phase. This is because the capture phase ends from document -> HTML -> body.
Event model (event handler)
An event means that the user or browser performs some kind of action. The function called in response to an event is called an event handler (or event model, event listener).
HTML event handler
Each event supported by a particular element can be specified as an HTML attribute using the name of the event handler. The value of the property must be executable JavaScript code.
<! <input type="button" value="on click" onclick="console.log('click me')">Copy the code
After the button is clicked, the console outputs a message. This interaction is achieved by specifying javaScript code values via the onclick attribute.
<! <input type="button" value="on click" onclick="showInfo()"> function showInfo() { console.log('click me') }Copy the code
Event handlers defined in HTML can also invoke scripts defined elsewhere on the page.
There is something special about event handlers specified in this way.
- A function is created to encapsulate the value of the property. This function has one
Special local variable event
And one of them isThe event object
γ
<input type="button" value="on click" onclick="console.log(event.type)"> <! Click -->Copy the code
In this function, the value this
The equivalent ofThe target element of the event
γ
<input type="button" value="on click" onclick="console.log(this.value)"> <! On click -->Copy the code
- This dynamically created wrapper function, whose
The scope chain is extended
.
<form method="post">
<input type="text" name="username" value="">
<input type="button" value="on click value" onclick="console.log(username.value)">
</form>
Copy the code
After the button is clicked, the value from the current input is printed. If the element is a form input box, the scope chain also contains form elements that can be accessed directly from other members of the same form.
The function corresponding to the event handler is equivalent to the one on the right
Question:
A question of timing
- It is possible that the HTML element is already on the page and the user is interacting with it, but the event handler code has not yet been loaded in
- To event handlers
Extension of the scope chain
Different results may result in different browsers- Rules for identifier resolution differ between javaScript engines, so accessing unqualified object members can lead to errors.
HTML
δΈJavaScript
Strong coupling- If you need to change the event handler, you have to change the code in two places (HTML, JS)
DOM0 event handler
We often use element.onclick = function(){} as the DOM0 event handler.
DOM0 event handlers have two ways of binding events, an inline model and a script model.
Inline schema
The inline model, also known as inline binding, binds events by directly using the function name as the attribute value of an EVENT in an HTML tag.
<button onclick="func () ">Copy the code
Disadvantages: violates W3C’s basic principle of separating HTML from JavaScript.
Script mode
The script model, also known as “dynamic binding,” binds by selecting a node in JavaScript and adding a listener to the node’s Onlick event.
Such as:
<body> <div id="myBtn">Copy the code
<script> let btn = document.getElementById('myBtn'); btn.onclick = function () { console.log('on cliclk'); // The event handler will run in the scope of the element, i.e. this equals the element console.log(this.id); // myBtn } </script>Copy the code
When assigning an event handler in DOM0 mode like this, the assigned function is treated as the element’s method. Therefore, the event handler runs in the scope of the element, i.e. **this equals the element **.
The advantages and disadvantages
Advantages: HTML and JavaScript separation, in line with the basic principles of W3C.
Disadvantages:
- Only one event of the same type can be bound to a node. If multiple events are bound, only the last event takes effect.
- Only bind events, no cancel events.
Btn. onclick = null // Remove the event handlerCopy the code
However, you can remove event handlers added by DOM0 mode by setting the value of the event handler property to NULL.
DOM2 event handler
Both ways of binding DOM0 events have limitations. In order to solve the limitations of DOM0 event handler, DOM2 event handler came into being.
Add event binding
Use addEventListener () for event binding.
Let BTN = document.getelementById (' BTN ') btn.addeventListener ('click', funcyion() {// Click triggered when the callback function}, true/false)Copy the code
AddEventListener receives three parameters: β The first parameter is the type of event to trigger. The main event name does not start with “on”. β‘ The second argument is the callback function executed when the event is triggered. (3) The third parameter is a model parameter that represents event bubbling or event capturing, false (default) represents event bubbling, and true represents event capturing.
In most cases, event handlers are added to the bubbling phase of the event flow, primarily for cross-browser compatibility. Registering an event handler to the capture phase is usually used to intercept an event before it reaches its specified destination. If interception is not required, do not use event capture.
Unbind events
One important difference between DOM2 and DOM0 is that dom2-bound events can be unbound. If the event binding is to be unbound, the callback function must use named functions instead of anonymous functions when the event is bound.
Unbind events using removeEventListener ().
Btn.removeeventlistener ("click", function name)Copy the code
advantages
Compare DOM0 event handler: 1) Implements the separation of HTML and JavaScript, meeting W3C requirements on the separation of content and behavior. 2) Events bound by DOM2 can be unbound. 3) Using DOM2, multiple events of the same type can be added to the same node. Multiple events can take effect simultaneously without being overwritten.
DOM2 can add multiple events of the same type to the same node
<body> <div id="myBtn">Copy the code
<script>
let btn = document.getElementById('myBtn');
btn.addEventListener('click', btnEvent1)
btn.addEventListener('click', btnEvent2)
function btnEvent1() {
console.log('btnEvent1');
}
function btnEvent2() {
console.log('btnEvent2');
}
</script>
Copy the code
IE event handler
IE implements methods similar to DOM2, namely attachEvent() and detachEvent().
Add event binding
Use attachEvent () for event binding.
Let BTN = document.getelementById (' BTN ') btn.attachevent ('onclick', funcyion() {// Callback function executed when onclick is triggered})Copy the code
AttachEvent receives two parameters: β The first parameter is the event type to be triggered. The main event name must start with on. β‘ The second argument is the callback function executed when the event is triggered.
Because IE8 and earlier only support event bubbling, event handlers added using attachEvent() are added to the bubbling phase.
Add multiple events of the same type to the same node
<body> <div id="myBtn">Copy the code
<script>
var btn = document.getElementById('myBtn');
btn.attachEvent('onclick', btnEvent1);
btn.attachEvent('onclick', btnEvent2);
function btnEvent1() {
console.log('btnEvent1');
}
function btnEvent2() {
console.log('btnEvent2');
}
</script>
Copy the code
Version issues:
This method is supported in earlier versions of IE, not in IE 11, not in Edge, and now the main browsers support DOM2 event handler addEventListener and removeEventListener.
Unbind events
If the event binding is to be unbound, the callback function must use named functions instead of anonymous functions when the event is bound.
Unbind the event using detachEvent ().
Btn.detachevent ("onclick", function name)Copy the code
Different from DOM handlers
1) IE event handlers fire in reverse order in which they were added.
2) Event handlers have different scopes.
With DOM0, DOM2, the this value in the event handler is equal to the target element. With attachEvent(), the event handler runs in the global scope, so this equals window.
<body> <div id="myBtn">Copy the code
<script>
var btn = document.getElementById('myBtn');
// btn.addEventListener('click', btnEvent1)
// btn.addEventListener('click', btnEvent2)
btn.attachEvent('onclick', btnEvent1);
btn.attachEvent('onclick', btnEvent2);
function btnEvent1() {
console.log(this === window, this.id);
console.log('btnEvent1');
}
function btnEvent2() {
console.log('btnEvent2');
}
</script>
Copy the code
Cross-browser event handlers
To handle events in a cross-browser compatible way, many developers choose to use a JavaScript library that abstracts the differences between browsers. It’s also easy to write your own cross-browser event handling code, relying heavily on capability detection. To ensure maximum compatibility with the event-handling code, simply have the code run in the bubbling phase.
var EventUtil = { addHandler: function (element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }, removeHandler: function (element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else if (element.detachEvent) { element.detachEvent("on" + type, handler); } else { element["on" + type] = null; }}};Copy the code
Both methods first detect the presence of DOM2 mode on the passed element.
If you have DOM2 mode, you use that mode, passing in the event type and event handler, along with a third argument false that represents the bubble phase.
Otherwise, if the IE mode exists, use this mode. Note that the event type must be preceded by “on” to be valid in IE8 and earlier versions.
Finally, use DOM0 mode (you don’t get this far in modern browsers). Note that when cancelling is used, DOM0 uses brackets to calculate the property name and assigns an event handler or NULL to the property.
Use:
var btn = document.getElementById("myBtn") var handler = function () { console.log("Clicked"); }; EventUtil.addHandler(btn, "click", handler); // eventUtil. removeHandler(BTN, "click", handler);Copy the code
The appendix
- JavaScript Advanced Programming (4th edition) – Matt Frisby
- Web front-end learning notes: HTML5+CSS3+JavaScript – Wang Tao, Yang Yancheng, Jiang Hao