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 article, 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 be positioned continuously through position calculation, 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('Binding to ul is successful 1');
	}
	function event2(){
		alert('Binding to ul is successful 2');
	}

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


Block event propagation/stop event bubbling

There will be this:

When we set click event listeners for window, document, body, and p respectively, if we click on p, the events of p, body, document, and window will pop up in turn.

Methods : event.stopPropagation() and event.cancelBubble (the latter is for IE8 and below browsers)

Usage :  

event.stopPropagation(); // Prevent further propagation of events, including bubbling and capturing, no parameters, not supported by IE8 and below
 event.cancelBubble=truel //true is to prevent bubbling

Example:

Main part of HTML code:

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

JS (unblocked):

	//Because of the event blocking on the p tag, the function is taken out separately
	function handle(){
		alert('click paragraph');
	}

	// Note the order of the listeners! ! !
	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=324502781&siteId=291194637