不是标题党, 如果可以把下面的链接指向的资源都理解透彻, 当然可以深入理解DOM
完全新手的话, 可以先看看我写的key concept后, 再看Odin的文章之后慢慢深入
Resource
推荐The Odin Project的这一章节, 前面带我们简单入门了基本操作, 之后在Assignment给出了很好的Event的补充资源, 在附加资源中更是全面的覆盖了DOM知识点
the odin project 附加资源: 内含一些适合入门加进阶的内容:
以下仅供参考
Key Concept:
DOM
what is DOM?
The DOM (or Document Object Model) is a tree-like representation of the contents of a webpage
- which like a tree
- using JS manipulate it
- every node in a tree is an object
DOM nodes examples:
documentthe omnipotent one
How to select a element(node) in the DOM?
let header = document.getElementById("balabala");let header = document.getElementByClassName("balabala");let header = document.getElementByTagName("balabala");let header = document.querySelector("balabala");- which is mostly used while it can use any CSS selector
header = document.querySelectorAll("balabala");- which return a "NodeList" object
Element attributes:
HTML / CSS stuff:
header.className = "header"header.id = "header"header.textContent = "AWESOME";header.innerText = "AWESOME";header.innerHTML = "AWESOME";header.style.backgroundColor = red;- which change CSS!
Manipulation:
header.parentNodeheader.childNodeheader.childrenheader.nextElementSibiling
how to create a element and update it to HTML?
Create:
let newheader = document.createElement("header");let newheader = document.createTextNode("just some text");Update:header.append(newHeader);header.appendChild(newHeader);header.insertBefore(newHeader);
Event
three way to click a button
btn.onclick = somefunction<button onclick="somefunction">this is a button </button>
Mostly used
btn.addEventListener('click', somefunction);- which is essential way to listen a event!
- the
somefunctionshould take in aEventobject event.targetrepresent the origin elementevent.typeshow the type(which is click for now) of the event etc.
Various Events
mouseover / mouseout
mouseenter / mouseleave
keyUp / keyDown
focus / blur
change / input / etc.
...
How Events Response? # Two main Event models
Event bubbling
- button
- div with the id container
- body
- html
- document
Event capturing
- document
- html
- body
- div with the id container
- button
DOM Level 2 Event flow
...
FULL NOTE
BELOW IS MY FULL NOTES WHICH IS KINDA REDUNDANT, SO JUST IGNORE IT.
Two main Event models
Event bubbling
- button
- div with the id container
- body
- html
- document
Event capturing
- document
- html
- body
- div with the id container
- button
DOM Level 2 Event flow
DOM level 2 events specify that event flow has three phases:
- First, event capturing occurs, which provides the opportunity to intercept the event.
- Then, the actual target receives the event.
- Finally, event bubbling occurs, which allows a final response to the event.
Event object
The following table shows the most commonly used properties and methods of the event object:
| Property / Method | Description |
|---|---|
| bubbles | true if the event bubbles |
| cancelable | true if the default behavior of the event can be canceled |
| currentTarget | the current element on which the event is firing |
| defaultPrevented | return true if the preventDefault() has been called. |
| detail | more information about the event |
| eventPhase | 1 for capturing phase, 2 for target, 3 for bubbling |
| preventDefault() | cancel the default behavior for the event. This method is only effective if the cancelable property is true |
| stopPropagation() | cancel any further event capturing or bubbling. This method only can be used if the bubbles property is true. |
| target | the target element of the event |
| type | the type of event that was fired |
Note that the event object is only accessible inside the event handler. Once all the event handlers have been executed, the event object is automatically destroyed.
e.g.
1. preventDefault()
For example, when you click a link, the browser navigates you to the URL specified in the href attribute:
<a href="https://www.javascripttutorial.net/">JS Tutorial</a>`
However, you can prevent this behavior by using the preventDefault() method of the event object:
let link = document.querySelector('a');
link.addEventListener('click',function(event) {
console.log('clicked');
event.preventDefault();
});
Note that the preventDefault() method does not stop the event from bubbling up the DOM.
An event can be canceled when its cancelable property is true.
2. stopPropagation()
The stopPropagation() method immediately stops the flow of an event through the DOM tree. However, it does not stop the browser’s default behavior.
let btn = document.querySelector('#btn');
btn.addEventListener('click', function(event) {
console.log('The button was clicked!');
event.stopPropagation();
});
document.body.addEventListener('click',function(event) {
console.log('The body was clicked!');
});
- 默认情况下,
addEventListener是在 冒泡阶段 监听事件的,所以 "The body was clicked!" 不会在捕获阶段触发。 - 如果你想在捕获阶段监听事件,可以设置
useCapture参数为true。
Without the stopPropagation() method, you would see two messages on the Console window.
However, the click event never reaches the body because the stopPropagation() was called on the click event handler of the button.
JavaScript Page Load Events
When you open a page, the following events occur in sequence:
DOMContentLoaded- the browser fully loaded HTML and completed building the DOM tree.
- However, it hasn’t loaded external resources like stylesheets and images.
- In this event, you can start selecting DOM nodes or initialize the interface.
load- the browser fully loaded the HTML and external resources like images and stylesheets.
When you leave the page, the following events fire in sequence:
beforeunload- fires before the page and resources are unloaded.
- You can use this event to show a confirmation dialog to confirm if you want to leave the page.
- By doing this, you can prevent data loss in case the user is filling out a form and accidentally clicks a link that navigates to another page.
unload- fires when the page has completely unloaded.
- You can use this event to send the analytic data or to clean up resources.
The following example illustrates how to handle the page load events
<!DOCTYPE html>
<html>
<head>
<title>JS Page Load Events</title>
</head>
<body>
<script>
addEventListener('DOMContentLoaded', (event) => {
console.log('The DOM is fully loaded.');
});
addEventListener('load', (event) => {
console.log('The page is fully loaded.');
});
addEventListener('beforeunload', (event) => {
// show the confirmation dialog
event.preventDefault();
// Google Chrome requires returnValue to be set.
event.returnValue = '';
});
addEventListener('unload', (event) => {
// send analytic data
});
</script>
</body>
</html>
JavaScript Mouse Events
mousedown, mouseup, and click events
When you click an element, there are no less than three mouse events fire in the following sequence:
- The
mousedownfires when you press the mouse button on the element. - The
mouseupfires when you release the mouse button on the element. - The
clickfires when onemousedownand onemouseupdetected on the element.
If you press the mouse button on an element, move your mouse cursor off the element, and then release the mouse button. The only mousedown event fires on the element.
Likewise, if you press the mouse button, move the mouse over the element, and release the mouse button, the only mouseup event fires on the element.
In both cases, the click event never fires.
dblclick event
-
mousedown -
mouseup -
click -
mousedown -
mouseup -
click -
dblclickIf you register bothclickanddblclickevent handlers on the same element you will not know whether the user has clicked or double-clicked the element.
mousemove
The mousemove event fires repeatedly whenever you move the mouse cursor around an element.
This mousemove event fires many times per second as the mouse is moved around, even if it is just by one pixel.
This may lead to a performance issue if the event handler function is complex.
To avoid the performance issue, it is a good practice to add mousemove event handler only when you need it and remove it as soon as it is no longer needed, like this:
element.onmousemove = mouseMoveEventHandler;
// ... // later, no longer use
element.onmousemove = null;
mouseover / mouseout
- The
mouseoverfires when the mouse cursor is outside of the element and then moves inside the boundaries of the element. - The
mouseoutfires when the mouse cursor is over an element and then moves another element.
mouseenter / mouseleave
- The
mouseenterfires when the mouse cursor is outside of an element and then moves inside the boundaries of the element. - The
mouseleavefires when the mouse cursor is over an element and then moves to the outside of the element’s boundaries. Bothmouseenterandmouseleavedoes not bubble and ==does not fire== when the mouse cursor moves over descendant elements.
key difference between mouseover and mouseenter etc.
1. Bubbling Behavior:
mouseover/mouseout: These events bubble up, meaning they trigger not only when the mouse moves over or out of the element but also when it interacts with any of the child elements. If you hover over a child element inside the parent,mouseoverandmouseoutwill fire for both the parent and the child.mouseenter/mouseleave: These events do not bubble. They only trigger when the mouse enters or leaves the element itself, ignoring any child elements. This makes them more efficient when you don’t want events firing multiple times when hovering over nested elements.
2. Firing Frequency:
mouseover/mouseout: These events can fire multiple times if you move your mouse across different parts of an element or its children.mouseenter/mouseleave: These events will fire only once when entering or leaving the element, making them more stable for detecting entry/exit without worrying about child elements.
When to Use:
mouseover/mouseout: Use when you want the event to detect interactions with both parent and child elements (and you're fine with bubbling).mouseenter/mouseleave: Use when you only care about the parent element and want to avoid the event firing for child elements.
Detecting mouse buttons
- 0: the main mouse button is pressed, usually the left button.
- 1: the auxiliary button is pressed, usually the middle button or the wheel button.
- 2: the secondary button is pressed, usually the right button.
- 3: the fourth button is pressed, usually the Browser Back button.
- 4: the fifth button is pressed, usually the Browser Forward button.
<!DOCTYPE html>
<html>
<head>
<title>JS Mouse Events - Button Demo</title>
</head>
<body>
<button id="btn">Click me with any mouse button: left, right, middle, ...</button>
<p id="message"></p>
<script>
let btn = document.querySelector('#btn');
// disable context menu when right-mouse clicked
btn.addEventListener('contextmenu', (e) => {
e.preventDefault();
});
// show the mouse event message
btn.addEventListener('mouseup', (e) => {
let msg = document.querySelector('#message');
switch (e.button) {
case 0:
msg.textContent = 'Left mouse button clicked.';
break;
case 1:
msg.textContent = 'Middle mouse button clicked.';
break;
case 2:
msg.textContent = 'Right mouse button clicked.';
break;
default:
msg.textContent = `Unknown mouse button code: ${event.button}`;
}
});
</script>
</body>
</html>
Modifier keys (shift alt ctrl)
<!DOCTYPE html>
<html>
<head>
<title>JS Modifier Keys Demo</title>
</head>
<body>
<button id="btnKeys">Click me with Alt, Shift, Ctrl pressed</button>
<p id="messageKeys"></p>
<script>
let btnKeys = document.querySelector('#btnKeys');
btnKeys.addEventListener('click', (e) => {
let keys = [];
if (e.shiftKey) keys.push('shift');
if (e.ctrlKey) keys.push('ctrl');
if (e.altKey) keys.push('alt');
if (e.metaKey) keys.push('meta');
let msg = document.querySelector('#messageKeys');
msg.textContent = `Keys: ${keys.join('+')}`;
});
</script>
</body>
</html>
Getting Screen Coordinates
The screenX and screenY properties of the event passed to the mouse event handler return the screen coordinates of the location of the mouse in relation to the entire screen.
On the other hand, the
clientX and clientY properties provide the horizontal and vertical coordinates within the application’s client area at which the mouse event occurred:
See the following demo:
<!DOCTYPE html>
<html>
<head>
<title>JS Mouse Location Demo</title>
<style>
#track {
background-color: goldenrod;
height: 200px;
width: 400px;
}
</style>
</head>
<body>
<p>Move your mouse to see its location.</p>
<div id="track"></div>
<p id="log"></p>
<script>
let track = document.querySelector('#track');
track.addEventListener('mousemove', (e) => {
let log = document.querySelector('#log');
log.innerText = `
Screen X/Y: (${e.screenX}, ${e.screenY})
Client X/Y: (${e.clientX}, ${e.clientY})`
});
</script>
</body>
</html>
side notes: The wheel event is triggered when the mouse wheel is used.
JavaScript Keyboard Events
There are three main keyboard events:
keydown– fires when you press a key on the keyboard and fires repeatedly while you’re holding down the key.keyup– fires when you release a key on the keyboard.keypress– fires when you press a character keyboard likea,b, orc, not the left arrow key, home, or end keyboard, … Thekeypressalso fires repeatedly while you hold down the key on the keyboard.
The keyboard events typically fire on the text box, though all elements support them. When you press a character key once on the keyboard, three keyboard events are fired in the following order:
keydownkeypresskeyup
Both keydown and keypress events are fired before any change is made to the text box,
whereas the keyup event fires after the changes have been made to the text box.
If you hold down a character key, the keydown and keypress are fired repeatedly until you release the key.
When you press a non-character key, the keydown event is fired first followed by the keyup event.
If you hold down the non-character key, the keydown is fired repeatedly until you release the key.
The keyboard event properties
The keyboard event has two important properties: key and code.
The key property returns the character that has been pressed
whereas the code property returns the physical key code.
For example, if you press the z character key, the event.key returns z and event.code returns KeyZ.
JavaScript Event Delegation
FROM
<ul id="menu">
<li><a id="home">home</a></li>
<li><a id="dashboard">Dashboard</a></li>
<li><a id="report">report</a></li>
</ul>
let home = document.querySelector('#home');
home.addEventListener('click',(event) => {
console.log('Home menu item was clicked');
});
let dashboard = document.querySelector('#dashboard');
dashboard.addEventListener('click',(event) => {
console.log('Dashboard menu item was clicked');
});
let report = document.querySelector('#report');
report.addEventListener('click',(event) => {
console.log('Report menu item was clicked');
});
TO
let menu = document.querySelector('#menu');
menu.addEventListener('click', (event) => {
let target = event.target;
switch(target.id) {
case 'home':
console.log('Home menu item was clicked');
break;
case 'dashboard':
console.log('Dashboard menu item was clicked');
break;
case 'report':
console.log('Report menu item was clicked');
break;
}
});
JavaScript event delegation benefits
When it is possible, you can have a single event handler on the document that will handle all the events of a particular type. By doing this, you gain the following benefits:
- Less memory usage, better performance.
- Less time is required to set up event handlers on the page.
- The
documentobject is available immediately. As long as the element is rendered, it can start functioning correctly without delay. You don’t need to wait for theDOMContentLoadedorloadevents.
JavaScript dispatchEvent
Events can be generated from code.
- First, create a new
Eventobject usingEventconstructor. - Then, trigger the event using
element.dispatchEvent()method.
Event constructor
To create a new event, you use the Event constructor like this:
let event = new Event(type, [,options]);
The Event constructor accepts two parameters:
- type
is a string that specifies the event type such as
'click'. - options
is an object with two optional properties:
bubbles: is a boolean value that determines if the event bubbles or not. If it istruethen the event is bubbled and vice versa.cancelable: is also a boolean value that specifies whether the event is cancelable when it istrue. By default, theoptionsobject is:
{ bubbles: false, cancelable: false}
For example, the following creates a new click event with the default options object:
let clickEvent = new Event('click');
dispatchEvent method
After creating an event, you can fire it on a target element using the dispatchEvent() method like this:
element.dispatchEvent(event);
For example, the following code shows how to create the click event and fire it on a button:
HTML:
<button class="btn">Test</button>
JavaScript:
let btn = document.querySelector('.btn');
btn.addEventListener('click', function () {
alert('Mouse Clicked');
});
let clickEvent = new Event('click');
btn.dispatchEvent(clickEvent);
- Use
event.isTrustedto examine whether the event is generated from code or user actions. It’s a good practice to use the specialized event constructor like MouseEvent instead of using the genericEventtype because these constructors provide more information specific to the events. For example, theMouseEventevent has many other properties such asclientXandclientY
JavaScript Custom Events
Creating JavaScript custom events
To create a custom event, you use the CustomEvent() constructor:
let event = new CustomEvent(eventType, options);
The CustomEvent() has two parameters:
- The
eventTypeis a string that represents the name of the event. - The
optionsis an object has thedetailproperty that contains any custom information about the event.
JavaScript custom event example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Custom Event</title>
</head>
<body>
<div class="note">JS Custom Event</div>
<script>
function highlight(elem) {
const bgColor = 'yellow';
elem.style.backgroundColor = bgColor;
// create the event
let event = new CustomEvent('highlight', {
detail: {
backgroundColor: bgColor
}
});
// dispatch the event
elem.dispatchEvent(event);
}
// Select the div element
let div = document.querySelector('.note');
// Add border style
function addBorder(elem) {
elem.style.border = "solid 1px red";
}
// Listen to the highlight event
div.addEventListener('highlight', function (e) {
addBorder(this);
// examine the background
console.log(e.detail);
});
// highlight div element
highlight(div);
</script>
</body>
</html>
How it works:
- First, declare the
highlight()function that highlights an element and triggers thehighlightevent. - Second, select the
<div>element by using the[querySelector()](https://www.javascripttutorial.net/javascript-dom/javascript-queryselector/)method. - Third, listen to the
highlightevent. Inside the event listener, call theaddBorder()function and show thedetailproperty in the Console. - Finally, call the
highlight()function that will trigger thehighlightevent.