JavaScript event delegation

Reference link:

Detailed explanation of JavaScript event delegation

concept

Event delegation is to delegate the function of an element in response to an event (click, keydown...) to another element. Generally speaking, the event of one or a group of elements is delegated to its parent or outer element, so the outer element is the one that actually binds the event. When the time responds to the element that needs to be bound, it will Through the event bubbling mechanism, the binding event of its outer element is triggered, and then the function is executed on the outer element.

Event Streaming/Event Propagation

Suppose a li tag is clicked and there is an a link inside the tag

(1) DOM0: There is no concept of event flow, events will not propagate

(2) IE event flow:

            #1. Event capturing: The click first occurs on the document, and then it is passed down to the body, list, list item, and finally to the link.

            #2. Event bubbling: The click occurs first on the link, and then bubbles up layer by layer until the document object.

(3) DOM2: One more event processing (target phase) than the IE event stream

            #1. Event Capture

            #2. Event Handling

            #3. Event Bubbling


principle

Event delegation is implemented using the event bubbling mechanism.

Features of event delegation:

        #1. You only need to delegate the events of the same element to the parent or the outer element, and you do not need to bind events to all elements, reducing memory usage

        #2. Dynamically added elements do not need to rebind events

        #3. The implementation of event delegation relies on the event bubbling mechanism, so events that do not support event bubbling are not suitable (Netscape only uses the capture method)

        #4. To add to the previous one, time such as focus and blur have no event bubbling mechanism and cannot be delegated; although mousemove and mouseout have event bubbling, they can only continuously calculate and locate by position, which is not suitable for high performance consumption. event delegation


Don't use event delegation

HTML:

<body>
	<ul id="myList">
		<li id="li-1">aaa</li>
		<li id="li-2">bbb</li>
		<li id="li-3">ccc</li>
	</ul>
</body>

JS:

	var myList=document.getElementById("myList");
	var li=myList.getElementsByTagName("li");

	for(var i=0;i<li.length;i++){
		li[i].onclick=function(e){
			var e=event || window.event; //window.event is IE compatible
			var target=e.target || e.srcElement; //Standard browser event.target, IE browser event.srcElement
			alert(e.target.id+': '+e.target.innerText);
		}
	}

Problems with DOM0 events:

        #1. Bind the same event to each list item, wasting memory

        #2. When a new element is dynamically added, you need to re-bind events to the element


Using event delegation

The same HTML code, the difference is the JS:

	var myList=document.getElementById("myList");
	myList.onclick=function(e){
		var e= event||window.event;
		var target=e.target ||e.srcElement;
		switch(target.id){
			case 'li-1':
				target.style.backgroundColor='red';
				break;
			case 'li-2':
				alert('this is the second item');
				break;
			case 'li-3':
				target.style.color='blue';
				break;
			default:
				alert('You avoided all options perfectly~');
		}
	}


Event delegation in jQuery

$('#myList').on('click','li',function(){
	alert(this.id);
});
/* //If there is no child element inside the element to which the event is bound, e.target is equivalent to this, and both point to the element to which the event is bound, otherwise e.target points to the child element of the element
$('#myList').on('click','li',function(e){
	alert(e.target.id);
});
*/

//////////////////////////////////////////////////////////////////////////////////////////////////////////

DOM2 event listener

addEventListener(event type [event.type], function [handle], whether to use the capture method [default false, that is, the bubbling mechanism is used])

attachEvent("on"+event.type , handle) (IE)

Features:

        #1. You can specify multiple listener functions for an event to solve the problem of event coverage

        #2. Listeners are independent of each other

        #3. IE8 and below are not supported, you need to use attachEvent(event.type , handle)

        function event1(){
		alert('给ul绑定成功1');
	}
	function event2(){
		alert('给ul绑定成功2');
	}

	var ul=document.querySelector('#myList');
	ul.addEventListener('click',event1,false); 
	ul.addEventListener('mouseout',event2,false);


阻断事件传播/停止事件冒泡

会有这种情况:

当我们分别给window , document , body,p均设置click的事件监听器时,如果在p上点击,就会依次弹出p,body,document,window的事件.

方法event.stopPropagation()event.cancelBubble(后者针对的是IE8及以下浏览器)

用法  

 event.stopPropagation();   //阻止事件的进一步传播,包括冒泡和捕捉,无参数,IE8及以下不支持
 event.cancelBubble=truel   //true为阻止冒泡

实例:

HTML代码主要部分:

<body>
	<p id="para">段落</p>
</body>

JS(未阻断):

	//因为要在p标签上做事件阻断,所以把函数单独拿出来
	function handle(){
		alert('click paragraph');
	}

	//注意监听器的顺序!!!
	document.body.addEventListener('click',handle,false);

	document.body.addEventListener('click',function(){
		alert('clicked body');
	},false);

	document.addEventListener('click',function(){
		alert('clicked document');
	},false);

	window.addEventListener('click',function(){
		alert('clicked window');
	},false);

JS(阻断,这是一种兼容性写法,推荐!):

function handle(e){
	alert('click paragraph');

	//阻断事件传播
	e=event|| window.event;
	if(e.stopPropagation){
		e.stopPropagation();
	}else{
		e.cancelBubble=true;
	}
}


防止默认行为

在浏览器模型中,有些事件自身就存在一些预定义行为。例如,单击链接会载入另一个页面。在某些情况下,我们需要禁用其默认行为。

方法event.preventDefault()event.returnValue=false;(IE)

实例:禁用默认行为,单击链接后,回答一个问题“are you sure you want to follow this link?”

HTML:

<body>
	<div>
		<a href="javascript:;">链接1</a>
		<a href="javascript:;">链接2</a>
	</div>
</body>

JS(兼容性写法,推荐!):

	//这里是禁用了所有链接的默认行为
	var links=document.getElementsByTagName("a");
	for(var i=0;i<links.length;i++){
		links[i].addEventListener('click',function(e){
			e=event||window.event;
			if(!confirm('are you sure you want to follow this link?')){
				if(e.preventDefault()){
					e.preventDefault();
				}else{
					e.returnValue=false;
				}
			}
		},false);
	}


事件解绑/移除监听器

方法event.removeEventListener(event.type , handle, boolean[默认false])event.detachEvent("on"+event.type , handle)(IE)


跨浏览器的事件监听器(推荐五颗星!!

var listenerEvent={
	getEvent:function(event){
		return event||window.event; //后者为IE
	},

	getTarget:function(event){
		return event.target||event.srcElement; //后者为IE
	},

	stopPropagation:function(){
		if(event.stopPropagation()){
			event.stopPropagation();
		}else{
			event.cancelBubble=true; //IE
		}
	},

	preventDefault:function(){
		if(event.preventDefault()){
			event.preventDefault();
		}else{
			event.returnValue=false;  //IE
		}
	},

	addListener:function(element,type,handle,boolean){ 
	//第一个参数为添加监听器的对象,第二个为事件类型,第三个为函数,第四个为是否采用捕捉法(默认false,即冒泡法)
		boolean=boolean||false; //设置boolean默认值为false
		if(element.addEventListener){
			element.addListener(type,handle,boolean);
		}else if(element.attachEvent){
			element.attachEvent("on"+type,handle);  //IE,注意在事件类型前面加了on,如click,这里需要写成onclick
		}else{
			element["on"+type]=handle; //不支持以上两种写法的备用方法
		}
	},

	removeListener:function(element,type,handle,boolean){
		boolean=boolean||false; //设置boolean默认值为false
		if(element.removeListener){
			element.removeListener(type,handle,boolean);
		}else if(element.detachEvent){
			element.detachEvent("on"+type,handle); //IE,注意在事件类型前面加了on,如click,这里需要写成onclick
		}else{
			element["on"+type]=null;//不支持以上两种写法的备用方法
		}
	}
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325638860&siteId=291194637