“This is the 8th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
The event flow model in JavaScrip is divided into three stages: event capture, event target and event bubbling.
Phase 1: capture phase, conduction from the Window object to the target node Phase 2: target phase, event is triggered on the target node phase 3: bubble phase, return window object from the target node
<html>
<body>
<div class="parent">
<div class="target">
</div>
</div>
</body>
</html>
Copy the code
Event Capturing
From the outside in, from the parent of the DOM tree to the child,document -> html -> body -> parent -> target
Event bubbling
From the inside out, from the child of the DOM tree to the parent,target -> parent -> body -> html -> document
Event Target
It refers to the first stage of the event bubbling, that is, bubblingtarget
Events are emitted, so the target phase is also treated as part of the event bubble
Event bubbling VS event capture
Event bubbling and event capture were proposed by Microsoft and Netscape respectively, but the W3C settled the debate by combining the two to create a unified standard — capture first, bubble later.
Binding of events
El.onclick =function(){};
Dom0-level events override each other (i.e., bind el to onclick and only one will be valid), so it is not recommended at this time
DOM2 event binding standard browser: el.adDeventListener (‘click’,function(){},false)
IE6-8:
el.attachEvent('onclick',function(){})
addEventListener
In JavaScript, the DOM’s addEventListener method is used to add event handles to the specified element. Syntax: element.addEventListener(event, function, useCapture)
element | The target element |
---|---|
event | Event name, such as “click” |
function | The function that is executed when an event is raised |
useCapture | Boolean value, true – Event handle incapture Phase execution; False – The default event handle is inThe bubbling Stage to perform |
Not all events can bubble or capture. For example, blur, Focus, load, and resize events do not support bubble or capture. See MDN for details.
Event capture
Let’s first guess the code below. When we click on a div with class target, what is the output order
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
const html = document.querySelector('html')
document.addEventListener('click'.() = >{console.log('the document capture')}, true)
html.addEventListener('click'.() = >{console.log('HTML capture')}, true)
document.body.addEventListener('click'.() = >{console.log('body capture')}, true)
parent.addEventListener('click'.() = >{console.log('the parent trap')}, true)
target.addEventListener('click'.() = >{console.log('target capture')}, true)
Copy the code
Document capture -> HTML capture -> body capture -> parent capture -> target capture will be output according to the rules of capture event flow model from the outside in
The event bubbling
Let’s change all of the above code from true to false and see what happens.
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
const html = document.querySelector('html')
document.addEventListener('click'.() = >{console.log('document' bubble.)}, false)
html.addEventListener('click'.() = >{console.log('HTML' bubble.)}, false)
document.body.addEventListener('click'.() = >{console.log('body bubbling')}, false)
parent.addEventListener('click'.() = >{console.log('parent' bubble.)}, false)
target.addEventListener('click'.() = >{console.log('target' bubble.)}, false)
Copy the code
According to the rules of the bubble event flow model from the outside in, the output target bubble -> parent bubble -> body bubble -> HTML bubble -> Document bubble
Event bubbling & event capture exists simultaneously
What if two event flow models exist at the same time?
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
const html = document.querySelector('html')
document.addEventListener('click'.() = >{console.log('the document capture')}, true)
document.addEventListener('click'.() = >{console.log('document' bubble.)}, false)
html.addEventListener('click'.() = >{console.log('HTML capture')}, true)
html.addEventListener('click'.() = >{console.log('HTML' bubble.)}, false)
document.body.addEventListener('click'.() = >{console.log('body capture')}, true)
document.body.addEventListener('click'.() = >{console.log('body bubbling')}, false)
parent.addEventListener('click'.() = >{console.log('the parent trap')}, true)
parent.addEventListener('click'.() = >{console.log('parent' bubble.)}, false)
target.addEventListener('click'.() = >{console.log('target capture')}, true)
target.addEventListener('click'.() = >{console.log('target' bubble.)}, false)
target.addEventListener('click'.() = >{console.log('target capture 1')}, true)
target.addEventListener('click'.() = >{console.log('target bubbling 1')}, false)
Copy the code
Principle:
- From the outside in, the capture proceeds, and the capture event is executed immediately
- Non-target nodes, catch first and bubble later
- Target nodes, executed in code written order (whether bubbling or capturing)
So it prints: Document capture -> HTML capture -> body capture -> parent capture -> target capture -> target capture 1 -> target bubble 1 -> parent bubble -> Body bubble -> HTML bubble -> document bubble
The event object
The first argument to an event handler is the current event object, which is usually received as either event or e.
event.target
We can use event.target to get the target of the current event. For example, in the example above, if target is clicked, then event.target is target. If parent is clicked then event.target is parent.
It is fixed that at any stage of an event, event.target is the target object of the current event.
const target = document.querySelector('.target')
// e.target depends on who you click on
document.addEventListener('click'.function (e){
console.log(e.target);// target
}, true)
document.addEventListener('click'.function (e){
console.log(e.target);// target
}, false)
target.addEventListener('click'.function (e){
console.log(e.target);// target
})
Copy the code
And this event. The currentTarget
If you do not use the arrow function or a function that is already bound to this as the event handler, the event. CurrentTarget will always refer to the event’s current handler.
Event bubble and capture phase, who does this point to in the handler function this is a common interview question.
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
const html = document.querySelector('html')
document.addEventListener('click'.function (e){
console.log(e.target);// target
console.log(e.currentTarget);// document
console.log(this);// document
}, true)
parent.addEventListener('click'.(e) = > {
console.log(e.target);// target
console.log(e.currentTarget);// parent
console.log(this);// window
}, false)
target.addEventListener('click'.function (e){
console.log(e.target);// target
console.log(e.currentTarget);// target
console.log(this);// target
})
Copy the code
How do I prevent event capture/bubbling
If we want the target event to fire without triggering the corresponding event of the parent element (that is, closing the bubble process), we should prevent this behavior by calling the Event stopPropagation method or stopImmediatePropagation method.
1. StopImmediatePropagation Method: The stopImmediatePropagation method acts on the current node and all subsequent nodes in the event chain. Its purpose is to stop the running of the event handlers of the current node and all subsequent nodes after the execution of the current event handler
2. StopPropagation method: The stopPropagation method is applied to subsequent nodes to stop the execution of event handlers of all subsequent nodes after the execution of all event handlers bound to the current element
The difference between stopPropagation and stopImmediatePropagation is that stopPropagation does not prevent the execution of other handlers on the current node, but it does prevent events on other subsequent nodes in the event flow model. StopImmediatePropagation prevents other handlers of the current node from executing based on the events of subsequent nodes in the event flow model.
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
parent.addEventListener('click'.(e) = > {
e.stopPropagation()
console.log('the parent capture 1');
}, true)
parent.addEventListener('click'.(e) = > {console.log('the parent capture 2'); },true)
parent.addEventListener('click'.(e) = > {console.log('the parent 1' bubble.)})
parent.addEventListener('click'.(e) = > {console.log('the parent 2' bubble.)})
target.addEventListener('click'.(e) = > {console.log('target' bubble.); })Copy the code
Print parent capture 1 -> parent capture 2
If you use stopImmediatePropagation:
const parent = document.querySelector('.parent')
const target = document.querySelector('.target')
parent.addEventListener('click'.(e) = > {
e.stopImmediatePropagation()
console.log('the parent capture 1');
}, true)
parent.addEventListener('click'.(e) = > {console.log('the parent capture 2'); },true)
parent.addEventListener('click'.(e) = > {console.log('the parent 1' bubble.)})
parent.addEventListener('click'.(e) = > {console.log('the parent 2' bubble.)})
target.addEventListener('click'.(e) = > {console.log('target' bubble.); })Copy the code
Only parent captures 1
Blocking default behavior
event.preventDefalut()
Certain events on certain nodes in js trigger some default behavior, For example, the click event of a tag triggers a jump, the Submit event of a form triggers the submission action, and the Click event of a button of type=submit triggers the Submit event of the outer form form, etc.
If we don’t want to trigger these behaviors, the event.preventdefalut () method is called to prevent them
<a href="https://baidu.com" id="baiduLink">https://baidu.com</a>
<script>
const baiduLink = document.querySelector('#baiduLink')
baiduLink.addEventListener('click'.(e) = > {
e.preventDefault()
})
</script>
Copy the code
Clicking on the A TAB now does not jump
The above is to introduce JS event binding, event flow model, I hope to help you.