search
HomeWeb Front-endJS TutorialSummary of js event listening mechanism (event capture)_javascript skills

In the process of front-end development, we often encounter the problem of adding events to page elements. There are many js methods for adding events. Some are directly added to the page structure, and some use some js event monitoring methods. Due to various browser Servers have different mechanisms for event bubbling and event monitoring. LE browser only has event bubbling and no event monitoring mechanism. The compatibility issue for event monitoring is the biggest problem:

1. Write event methods directly on the page structure

function eventfun(){ 
//console.log(this); 
} 
<input type="button" onclick="eventfun()" value="button" />//这里涉及到一个this作用域的问题,eventfun再这里是一个全局函数, 对象是[object Window],this指向的是window.

To solve the problem of this scope, you can use the method of adding event variables to the global function, and pass this object as a parameter to the function inside the page structure

<input type="button" onclick="eventfun2(this)" value="button2" /> 
function eventfun2(eve){//在这里把事件对象作为参数传递到全局方法里 
eve.name="alex"; 
window.name="robin"; 
console.log(this);//[object Window] 
console.log(eve);// [object HTMLInputElement] 
console.log(this.name);// robin 
console.log(eve.name);// alexvar 
self=eve; 
console.log(this.name);//robin 
console.log(self.name);//alex 
alert(window.name); 
alert(self.name); 
}

2. Using the method of assigning values ​​to event attributes is a method of binding events. However, the limitation of this method is that it can only bind one method to the event. If multiple methods are bound, the next method will be used. Subject to

HTMLElementobject.onclick = fucntion(){//Using this method of assigning values ​​to event attributes, the pointer of this will point to the window object, not the event object, so this method is a reference

//js code 
fun1(); 
fun2(); 
fun3(); 
console.log(this);//window.object 
} 
function dosomething(){ 
//js code 
} 
HTMLElementobject.onclick = dosomething;//使用这种为事件对象属性赋值的形式,this指针指向事件执行对象 
console.log(this);//htmlElementObject

3. Event propagation - bubbling and capturing
The DOM event standard defines two event flows that are significantly different and may have a considerable impact on your application. The two event streams are capturing and bubbling. Like many Web technologies, Netscape and Microsoft each implemented them differently before they became standards. Netscape chose to implement the capture event stream, and Microsoft implemented the bubbling event stream. Fortunately, the W3C decided to use a combination of these two methods, and most new browsers follow both event streaming methods.
By default, events use the bubbling event stream and do not use the capturing event stream. However, in Firefox and Safari, you can explicitly specify to use the capture event stream by passing the useCapture parameter when registering the event and setting this parameter to true.
Bubbling event stream
When an event is triggered on a certain DOM element, such as the user clicking the mouse on the customer name node, the event will follow the parent nodes that the node inherits from and bubble through the entire DOM node hierarchy until it encounters the node that is attached to it. The node of the event type handler. At this time, the event is an onclick event. Event bubbling can be terminated at any time during the bubbling process. In browsers that comply with W3C standards, you can call the stopPropagation() method on the event object. In Internet Explorer, you can set the cancelBubble property of the event object to true. . If you don't stop the propagation of the event, the event will keep bubbling through the DOM until it reaches the document root.
Capture event stream
Event processing will start from the root of the DOM hierarchy, rather than starting from the target element that triggered the event. The event is passed down from all ancestor elements of the target element in order. In this process, the event will be captured by each inherited element from the document root to the event target element. If the event listener sets the useCapture attribute to true when it is registered, then they can be dispatched to any element during this period. element to handle the event; otherwise, the event is then passed to the next element on the path to the derived element, up to the target element. After the event reaches the target element, it will then bubble up through the DOM nodes.
Modern event binding methods
As discussed in the previous lesson, there are many drawbacks to using traditional event binding, such as the inability to register multiple event handlers for the same event on an object. Browsers and the W3C have not taken this into consideration, so in modern browsers, they have their own methods for binding events.
W3C DOM
obj.addEventListener(evtype,fn,useCapture)——Method provided by W3C to add event handling function. obj is the object to add the event, evtype is the event type without on prefix, fn is the event processing function, if useCapture is true, the event processing function is executed in the capture phase, otherwise it is executed in the bubbling phase
obj.removeEventListener(evtype,fn,useCapture)——Method provided by W3C to delete event handler function
Microsoft IE method
obj.attachEvent(evtype,fn)——The method provided by IE to add event processing function. obj is the object to add the event, evtype is the event type, with on prefix, fn is the event processing function, IE does not support event capture
obj.detachEvent(evtype,fn,)——The method provided by IE to delete event processing functions. evtype contains the on prefix

Methods to integrate the two

function addEvent(obj,evtype,fn,useCapture) { 
if (obj.addEventListener) { 
obj.addEventListener(evtype,fn,useCapture); 
} else { 
obj.attachEvent("on"+evtype,fn);//IE不支持事件捕获 
} else { 
obj["on"+evtype]=fn;//事实上这种情况不会存在 
} 
} 
function delEvent(obj,evtype,fn,useCapture) { 
if (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} else { 
obj.detachEvent("on"+evtype,fn); 
} else { 
obj["on"+evtype]=null; 
} 
}

There is a problem with IE's attach method. When using attachEvent, inside the event processing function, this points to window, not obj! Of course, there is a solution for this!

But IE’s attachEvent method has another problem. The same function can be registered to the same object and the same event multiple times. The solution: abandon IE’s attachEvent method! The attachEvent method under IE does not support capture, and is not much different from traditional event registration (except that it can bind multiple event processing functions), and IE's attachEvent method has a memory leak problem!
addEvent,delEvent modern version

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>js事件监听</title> 
<style> 
table td{font:12px; border-bottom:1px solid #efefef;} 
</style> 
</head> 

<body> 
<div id="outEle" style="padding:10px; border:1px solid #b2b2b2; background:#efefef;"> 
<input type="button" onclick="eventfun()" id="button" value="button" /><br /> 
<input type="button" onclick="eventfun2(this);" id="button2" value="button2" /><br /> 
<input type="button" id="button3" value="button3" /><br /> 
<input type="button" id="button4" value="button4" /><br /> 
<table id="htmlEleTable" width="100%" border="0" style="border:1px solid #b2b2b2; background:#fff;"> 
<tr id="1111"><td>111111111111111111111111111111</td></tr> 
<tr id="22222"><td>222222222222222222222222222222</td></tr> 
<tr id="33333"><td>333333333333333333333333333333</td></tr> 
<tr id="4444"><td>444444444444444444444444444444</td></tr> 
<tr id="55555"><td>555555555555555555555555555555</td></tr> 
</table> 
</div> 
<script language="javascript" type="text/javascript"> 
function eventfun(){//1.直接把js方法写在页面结构上 
console.log(this);//这里涉及到一个this作用域的问题,eventfun再这里是一个全局函数, 对象是window,this指向的是window 
alert(this); 
} 
function eventfun2(eve){//在这里把事件对象作为参数传递到全局方法里 
eve.name="alex";// 
window.name="robin"; 
console.log(this);//[object Window] 
console.log(eve);// [object HTMLInputElement] 
console.log(this.name);// robin 
console.log(eve.name);// alex 
var self=eve; 
console.log(this.name);//robin 
console.log(self.name);//alex 
alert(window.name); 
alert(self.name); 
} 
function eventfun3(){//1.直接把js方法写在页面结构上 
console.log(this);//这里涉及到一个this作用域的问题,eventfun再这里是一个全局函数, 对象是window,this指向的是window 
console.log(this.id); 
alert(this); 
alert(this.id); 
//var outEleObj = EventUtil.$("outEle"); 
//removeEvent(outEleObj,"click",eventfun3); 
} 
/* 
var EventUtil = {}; 
EventUtil.$ = function(id){ 
return document.getElementById(id); 
} 
EventUtil.openmes = eventfun3; 
EventUtil.addEventHandle = function(eventTarget,eventtype,eventHandle){//定义事件监听的对象元素,事件类型,事件函数 
if(eventTarget.attachEvent){ 
eventTarget.attachEvent("on"+eventtype,eventHandle); 
}else if(eventTarget.addEventListener){ 
eventTarget.addEventListener(eventtype,eventHandle,false) 
}else{ 
eventTarget["on" + eventtype] = null; 
} 

}; 
EventUtil.deleEventHandle = function(eventTarget,eventtype,eventHandle){//定义事件监听的对象元素,事件类型,事件函数 
if(eventTarget.detachEvent){ 
alert("on"+eventtype); 
alert("on"+eventHandle); 
eventTarget.detachEvent("on"+eventtype,eventHandle); 
}else if(eventTarget.removeEventListener){ 
eventTarget.removeEventListener(eventtype,eventHandle,false) 
}else{ 
eventTarget["on" + eventtype] = null; 
} 

};*/ 
var EventUtil={ 
$:function(id){ 
return document.getElementById(id); 
}, 
but4fun:function(){ 
console.log(this); 
this.addEventHandle(); 
}, 
eventfun3:function (){ 
console.log(this); 
alert(this); 
delEvent(obj,evtype,fn,useCapture); 
} 
} 
/***使用addEventListener,attachEvent进行dom事件的监听 
function addEvent(obj,evtype,fn,useCapture){ 
if (obj.addEventListener) { 
obj.addEventListener(evtype,fn,useCapture); 
}else if(obj.attachEvent){ 
obj.attachEvent("on"+evtype,function () { 
fn.call(obj); 
}); 
}else { 
obj["on"+evtype]=fn;//事实上这种情况不会存在 
} 
} 
function delEvent(obj,evtype,fn,useCapture) { 
if (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} else if(obj.detachEvent){ 
obj.detachEvent("on"+evtype,fn); 
} else { 
obj["on"+evtype]=null; 
} 
} 



function addEvent(obj,evtype,fn,useCapture) { 
if (obj.addEventListener) {//优先考虑W3C事件注册方案 
obj.addEventListener(evtype,fn,!!useCapture); 
} else {//当不支持addEventListener时(IE),由于IE同时也不支持捕获,所以不如使用传统事件绑定 
if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;} 
//为每个事件处理函数分配一个唯一的ID 

if (!obj.__EventHandles) {obj.__EventHandles={};} 
//__EventHandles属性用来保存所有事件处理函数的引用 

//按事件类型分类 
if (!obj.__EventHandles[evtype]) {//第一次注册某事件时 
obj.__EventHandles[evtype]={}; 
if (obj["on"+evtype]) {//以前曾用传统方式注册过事件处理函数 
(obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//添加到预留的0位 
//并且给原来的事件处理函数增加一个ID 
} 
obj["on"+evtype]=addEvent.execEventHandles; 
//当事件发生时,execEventHandles遍历表obj.__EventHandles[evtype]并执行其中的函数 
} 
} 
} 

addEvent.__EventHandlesCounter=1;//计数器,0位预留它用 
addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行 
if (!this.__EventHandles) {return true;} 
evt = evt || window.event; 
var fns = this.__EventHandles[evt.type]; 
for (var i in fns) { 
fns[i].call(this); 
} 
}; 
/* 
function delEvent(obj,evtype,fn,useCapture) { 
if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数 
obj.removeEventListener(evtype,fn,!!useCapture); 
} else { 
if (obj.__EventHandles) { 
var fns = obj.__EventHandles[evtype]; 
if (fns) {delete fns[fn.__EventID];} 
} 
} 
} 

function fixEvent(evt) {//fixEvent函数不是单独执行的,它必须有一个事件对象参数,而且只有事件发生时它才被执行!最好的方法是把它整合到addEvent函数的execEventHandles里面 
if (!evt.target) { 
evt.target = evt.srcElement; 
evt.preventDefault = fixEvent.preventDefault; 
evt.stopPropagation = fixEvent.stopPropagation; 
if (evt.type == "mouseover") { 
evt.relatedTarget = evt.fromElement; 
} else if (evt.type =="mouseout") { 
evt.relatedTarget = evt.toElement; 
} 
evt.charCode = (evt.type=="keypress")&#63;evt.keyCode:0; 
evt.eventPhase = 2;//IE仅工作在冒泡阶段 
evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间 
} 
return evt; 
} 
fixEvent.preventDefault =function () { 
this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent 
}; 
fixEvent.stopPropagation =function () { 
this.cancelBubble = true; 
};*/ 
//console.log(EventUtil.$("button3"));//返回EventUtil函数的对象属性 
//EventUtil.$("button3").onclick= eventfun;//2.使用为对象事件属性赋值的方法来实现事件的监听 
//EventUtil.$("button3").onclick= eventfun2;//为事件属性添加多个方法时,为后者 
//EventUtil.$("button3").onclick= eventfun;//事件捕获是从事件对象逐层外父级检察一直到window对象 
var EventUtil =function(){ 
function getByid(id){ 
return document.getElementById(id); 
}; 
// written by Dean Edwards, 2005 
// with input from Tino Zijdel, Matthias Miller, Diego Perini 

// http://dean.edwards.name/weblog/2005/10/add-event/ 

function addEvent(element, type, handler) { 
if (element.addEventListener) { 
element.addEventListener(type, handler, false); 
} else { 
// assign each event handler a unique ID 
if (!handler.$$guid) handler.$$guid = addEvent.guid++; 
// create a hash table of event types for the element 
if (!element.events) element.events = {}; 
// create a hash table of event handlers for each element/event pair 
var handlers = element.events[type]; 
if (!handlers) { 
handlers = element.events[type] = {}; 
// store the existing event handler (if there is one) 
if (element["on" + type]) { 
handlers[0] = element["on" + type]; 
} 
} 
// store the event handler in the hash table 
handlers[handler.$$guid] = handler; 
// assign a global event handler to do all the work 
element["on" + type] = handleEvent; 
} 
}; 
// a counter used to create unique IDs 
addEvent.guid = 1; 

function removeEvent(element, type, handler) { 
if (element.removeEventListener) { 
element.removeEventListener(type, handler, false); 
} else { 
// delete the event handler from the hash table 
if (element.events && element.events[type]) { 
delete element.events[type][handler.$$guid]; 
} 
} 
}; 

function handleEvent(event) { 
var returnValue = true; 
// grab the event object (IE uses a global event object) 
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); 
// get a reference to the hash table of event handlers 
var handlers = this.events[event.type]; 
// execute each event handler 
for (var i in handlers) { 
this.$$handleEvent = handlers[i]; 
if (this.$$handleEvent(event) === false) { 
returnValue = false; 
} 
} 
return returnValue; 
}; 

function fixEvent(event) { 
// add W3C standard event methods 
event.preventDefault = fixEvent.preventDefault; 
event.stopPropagation = fixEvent.stopPropagation; 
return event; 
}; 
fixEvent.preventDefault = function() { 
this.returnValue = false; 
}; 
fixEvent.stopPropagation = function() { 
this.cancelBubble = true; 
}; 
function tableAddEvent(){ 

}; 

return{ 
add:addEvent, 
remove:removeEvent, 
$:getByid 
} 
}(); 

var outEleObj = EventUtil.$("outEle"); 
//addEvent.apply(EventUtil,[outEleObj,"click",eventfun3]); 
//EventUtil.add(outEleObj,"click",eventfun3); 
var inputObj = EventUtil.$("button4"); 
var tableEle = EventUtil.$("htmlEleTable"); 
var tabTrEle = tableEle.getElementsByTagName("tr"); 
EventUtil.add(tableEle,"click",eventfun3); 
for (i=0; i<tabTrEle.length; i++){ 
EventUtil.add(tabTrEle[i],"click",eventfun3); 
} 
EventUtil.remove(tableEle,"click",eventfun3);//事件冒删除方法 
EventUtil.add(tableEle,"click",eventfun3);//事件冒泡添加方法 
//EventUtil.add(inputObj,"click",eventfun3); 
//EventUtil.remove(outEleObj,"click",eventfun3); 
//console.log(addEvent); 
//addEvent(inputObj,"click",eventfun3,true); 
//delEvent(outEleObj,"click",eventfun3,false); 
</script> 
</body> 
</html>

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
js中点击事件为什么不能重复执行js中点击事件为什么不能重复执行May 07, 2024 pm 06:36 PM

JavaScript 中的点击事件不能重复执行,原因在于事件冒泡机制。为了解决此问题,可以采取以下措施:使用事件捕获:指定事件侦听器在事件冒泡之前触发。移交事件:使用 event.stopPropagation() 阻止事件冒泡。使用计时器:在一段时间后再次触发事件侦听器。

有效阻止事件冒泡的方法有效阻止事件冒泡的方法Feb 19, 2024 pm 08:25 PM

如何有效地阻止事件冒泡,需要具体代码示例事件冒泡是指当一个元素上的事件触发时,父级元素也会收到相同的事件触发,这种事件传递机制有时会给网页开发带来麻烦,因此我们需要学习如何有效地阻止事件冒泡。在JavaScript中,我们可以通过使用事件对象的stopPropagation()方法来阻止事件冒泡。该方法可以在事件处理函数中调用,以停止事件继续传播到父级元素。

利用JavaScript和腾讯地图实现地图事件监听功能利用JavaScript和腾讯地图实现地图事件监听功能Nov 21, 2023 pm 04:10 PM

很抱歉,但我无法为您提供完整的代码示例。不过我可以为您提供一个基本的思路和示例代码段,以供参考。下面是一个简单的JavaScript和腾讯地图结合的示例,用于实现地图事件监听的功能://引入腾讯地图的APIconstscript=document.createElement('script');script.src='https://map.

事件捕获有什么作用事件捕获有什么作用Nov 01, 2023 pm 01:16 PM

事件捕获的作用包括方便获取目标元素和上下文信息、有效防止事件冒泡、自定义事件处理逻辑和提高页面响应速度等。详细介绍:1、方便获取目标元素和上下文信息,在事件捕获阶段,当一个事件发生时,浏览器会从最外层元素开始逐层向下查找与该事件相关联的元素,直到找到目标元素为止;2、有效防止事件冒泡,在事件模型中,一个事件发生时,会从最外层元素开始逐层向下传递,这个过程被称为事件冒泡等等。

前端开发中的事件冒泡和事件捕获的实际应用案例前端开发中的事件冒泡和事件捕获的实际应用案例Jan 13, 2024 pm 01:06 PM

事件冒泡与事件捕获在前端开发中的应用案例事件冒泡和事件捕获是前端开发中经常用到的两种事件传递机制。通过了解和应用这两种机制,我们能够更加灵活地处理页面中的交互行为,提高用户体验。本文将介绍事件冒泡和事件捕获的概念,并结合具体的代码示例,展示它们在前端开发中的应用案例。一、事件冒泡和事件捕获的概念事件冒泡(EventBubbling)事件冒泡是指在触发一个元

什么是事件冒泡事件捕获什么是事件冒泡事件捕获Nov 21, 2023 pm 02:10 PM

事件冒泡和事件捕获是指在HTML DOM中处理事件时,事件传播的两种不同方式。详细介绍:1、事件冒泡是指当一个元素触发了某个事件,该事件将从最内层的元素开始传播到最外层的元素。也就是说,事件首先在触发元素上触发,然后逐级向上冒泡,直到达到根元素;2、事件捕获则是相反的过程,事件从根元素开始,逐级向下捕获,直到达到触发事件的元素。

vue中常用的修饰符vue中常用的修饰符May 08, 2024 pm 04:27 PM

Vue.js 的修饰符用于修改指令行为,常用的修饰符包括:延迟执行(.lazy)、缓存计算结果(.memo)、强制转换为数字(.number)、修剪空格(.trim)、阻止默认行为(.prevent)、阻止事件冒泡(.stop)、仅执行一次(.once)、仅在当前元素触发(.self)、在事件捕获阶段触发(.capture)、在元素进入 DOM 时触发(.enter)、在元素离开 DOM 时触发(.leave)。

事件冒泡引发的常见问题与解决方案事件冒泡引发的常见问题与解决方案Feb 20, 2024 pm 06:48 PM

事件冒泡(eventbubbling)是指在DOM中,当一个元素上的事件被触发时,它会向上冒泡到该元素的父级元素,再向上冒泡到更高级别的父级元素,直至冒泡到文档的根节点。虽然事件冒泡在许多情况下非常有用,但有时它也会引发一些常见的问题。本文将讨论一些常见的问题,并提供解决方案。第一个常见问题是多次触发事件。当一个元素上的事件冒泡到了多个父级元素时,可能会导

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)