JavaScript的多种事件
In this section, we review the various mechanisms and discuss which ones you should use.
Event handler properties 事件处理属性(特性)
Event handler properties 事件处理属性(特性)
const btn = document.querySelector('button'); btn.onclick = function() { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; }
onclick 特性(属性)property 是event handler property(事件处理 的东西,事件处理的属于他的性质), 被用在上面的情况。
这个属性就像button的属性,比如 btn.textContent, btn.style, 但是它是一个特别的类型,你给它赋值一些代码,当事件被触发时候,代码会运行。
You could also set the handler property to be equal to a named function name( like we saw in Build your own
Inline event handlers -- don't use these
keeping your JavaScript separate is best practice;
Even in a single file, inline event handlers are not a good idea. One button is OK, but what if you had 100 buttons?
const buttons = document.querySelectorAll('button'); for (let i = 0; i < buttons.length; i++) { buttons[i].onclick = bgChange; }
buttons.forEach(function(button) { button.onclick = bgChange; });
Adding and removing event handlers
const btn = document.querySelector('button'); function bgChange() { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; }
btn.addEventListener('click', bgChange);btn.addEventListener('click', function() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; });
The following two handlers wouldn't both be applied:
myElement.onclick = functionA; myElement.onclick = functionB;
The second line overwrites the value of onclick set by the first line. What would work, however, is the following:
myElement.addEventListener('click', functionA); myElement.addEventListener('click', functionB);
Both functions would now run when the element is selected.
AbortController
The AbortController interface represents a controller object that allows you to abort one or more Web requests as and when desired.
You can create a new AbortController object using the AbortController() constructor. Communicating with a DOM request is done using an AbortSignal object.
const controller = new AbortController(); btn.addEventListener('click', function() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; }, { signal: controller.signal }); // pass an AbortSignal to this handler
Then the event handler created by the code above can be removed like this:
controller.abort(); // removes any/all event handlers associated with this controller
function bgChange(e) { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; e.target.style.backgroundColor = rndCol; console.log(e); } btn.addEventListener('click', bgChange);
1. 事件属性
2. inline 事件处理
3. 增加、移除事件监听
const form = document.querySelector('form'); const fname = document.getElementById('fname'); const lname = document.getElementById('lname'); const para = document.querySelector('p'); form.onsubmit = function(e) { if (fname.value === '' || lname.value === '') { e.preventDefault(); para.textContent = 'You need to fill in both names!'; } }
Event bubbling and capture
Bubbling and capturing explained
When an event is fired on an element that has parent elements (in this case, the <video> has the <div> as a parent), modern browsers run three different phases — the capturing phase, the target phase, and the bubbling phase.
三个阶段,但是在冒泡阶段注册事件
三个阶段,但是在冒泡阶段注册事件
In the capturing phase:
- The browser checks to see if the element's outer-most ancestor (<html>) has an onclick event handler registered on it for the capturing phase, and runs it if so.
- Then it moves on to the next element inside <html> and does the same thing, then the next one, and so on until it reaches the direct parent of the element that was actually selected.
In the target phase:
- The browser checks to see if the target property has an event handler for the click event registered on it, and runs it if so.
- Then, if bubbles is true, it propagates the event to the direct parent of the selected element, then the next one, and so on until it reaches the <html> element. Otherwise, if bubbles is false, it doesn’t propagate the event to any ancestors of the target.
In the bubbling phase, the exact opposite of the capturing phase occurs:
- The browser checks to see if the direct parent of the element selected has an onclick event handler registered on it for the bubbling phase, and runs it if so.
- Then it moves on to the next immediate ancestor element and does the same thing, then the next one, and so on until it reaches the <html> element.
In modern browsers, by default, all event handlers are registered for the bubbling phase. So in our current example, when you select the video, the event bubbles from the <video> element outwards to the <html> element. Along the way:
- It finds the video.onclick... handler and runs it, so the video first starts playing.
- It then finds the videoBox.onclick... handler and runs it, so the video is hidden as well.
现代浏览器中,默认情况下,为冒泡阶段注册所有事件处理程序。因此,在我们当前的示例中,当您选择视频时,事件从<video>元素向外冒泡到<html>元素。沿途:
它会找到视频。单击。。。处理程序并运行它,因此视频首先开始播放。
然后找到视频框。单击。。。处理程序并运行它,因此视频也被隐藏。
它会找到视频。单击。。。处理程序并运行它,因此视频首先开始播放。
然后找到视频框。单击。。。处理程序并运行它,因此视频也被隐藏。
Note: Event listeners registered for the <html> element aren’t at the top of hierarchy. For example, event listeners registered for the window and document objects are higher in the hierarchy.
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
/* * source 1: https://dom.spec.whatwg.org/#dom-event-eventphase * source 2: https://stackoverflow.com/a/4616720/15266715 */ let evtPhasestr = ["NONE: ", "CAPTURING_PHASE: ", "AT_TARGET: ", "BUBBLING_PHASE: "]; var logElement = document.getElementById('log'); function log(msg) { logElement.innerHTML += ('<p>' + msg + '</p>'); } function phase(evt) { log(evtPhasestr[evt.eventPhase] + this.firstChild.nodeValue.trim()); } function gphase(evt) { log(evtPhasestr[evt.eventPhase] + evt.currentTarget) } function clearOutput() { logElement.innerHTML = ""; } var divs = document.getElementsByTagName('div'); for (var i = 0; i < divs.length; i++) { divs[i].addEventListener('click', phase, true); divs[i].addEventListener('click', phase, false); } document.addEventListener('click', gphase, true); document.addEventListener('click', gphase, false); window.addEventListener('click', gphase, true); window.addEventListener('click', gphase, false); var clearButton = document.getElementById('clear'); clearButton.addEventListener('click', clearOutput);
停止冒泡
video.onclick = function(e) { e.stopPropagation(); video.play(); };
As mentioned above, by default all event handlers are registered in the bubbling phase, and this makes more sense most of the time.
If you really want to register an event in the capturing phase instead, you can do so by registering your handler using addEventListener(), and setting the optional third property to true.
阅读量: 419
发布于:
修改于:
发布于:
修改于: