zoukankan      html  css  js  c++  java
  • js事件委托的方式绑定详解

    js事件绑定

    事件绑定,这里使用了冒泡的原理,从点击的元素开始,递归方式的向父元素传播事件,这样做的好处是对于大量要处理的元素,不必为每个元素都绑定事件,只需要在他们的父元素上绑定一次即可,提高性能。还有一个好处就是可以处理动态插入dom中的元素,直接绑定的方式是不行的。

    之前一直使用的是jquery的on方法做这样的事情,前几天看到公司项目中有实现这种方式的源代码,拿来仔细研究研究,跟大家分享分享。

    function $bindAction(dom, event, listeners) {
    	#这里的dom为绑定事件的元素,比如document.body
    	#event为绑定的事件,比如click
    	#listeners是待执行的事件对象
    	$addEvent(dom, event, function(e) {
    		#这里获取事件e
    		#获取点击的元素src
    		var e = e || window.event,
    			src = e.target || e.srcElement,
    			action,
    			returnVal;
    
    		#模拟冒泡的方式,先是src,然后是src.parentNode,再然后是src.parentNode.parent.Node
    		#当前dom元素等于事件绑定的dom元素的时候,停止“冒泡”
    		while (src && src !== dom) {
    			#循环获取dom元素的attr-action属性,
    			action = src.getAttribute('attr-action');
    			#如果当前dom元素存在attr-action属性,并且事件对象中有该属性值的函数,执行这个函数
    			#将事件e、当前dom元素、元素的属性attr-action值传给要执行的函数
    			if (listeners[action]) {
    				returnVal = listeners[action]({
    					src : src,
    					e : e,
    					action : action
    				});
    				#如果上面的函数执行之后返回false,停止继续“冒泡”
    				if (returnVal === false) {
    					break;
    				}
    			}
    			#获取当前dom元素的父元素节点
    			src = src.parentNode;
    		}
    	});
    };
    
    function $addEvent(obj, type, handle) {
    	if(!obj || !type || !handle) {
    		return;
    	}
    	#绑定事件到多个对象,递归调用
    	if( obj instanceof Array) {
    		for(var i = 0, l = obj.length; i < l; i++) {
    			$addEvent(obj[i], type, handle);
    		}
    		return;
    	}
    	#绑定多个事件,递归调用
    	if( type instanceof Array) {
    		for(var i = 0, l = type.length; i < l; i++) {
    			$addEvent(obj, type[i], handle);
    		}
    		return;
    	}
    	#下面这一大段用来记录当前页面一共绑定了多少个事件,以及事件的相关信息
    	#以及某个对象上面绑定的事件id
    	window.__allHandlers = window.__allHandlers || {};
    	window.__Hcounter = window.__Hcounter || 0;
    	function setHandler(obj, type, handler, wrapper) {
    		obj.__hids = obj.__hids || [];
    		var hid = 'h' + ++window.__Hcounter;
    		obj.__hids.push(hid);
    		window.__allHandlers[hid] = {
    			type : type,
    			handler : handler,
    			wrapper : wrapper
    		}
    	}
    	#这个里面的apply是为了修改绑定事件所执行函数中的this
    	#这个在低版本的IE中才真正起作用
    	function createDelegate(handle, context) {
    		return function() {
    			return handle.apply(context, arguments);
    		};
    	}
    
    	#绑定事件,记录事件绑定信息
    	if(window.addEventListener) {
    		var wrapper = createDelegate(handle, obj);
    		setHandler(obj, type, handle, wrapper)
    		obj.addEventListener(type, wrapper, false);
    	}
    	else if(window.attachEvent) {
    		var wrapper = createDelegate(handle, obj);
    		setHandler(obj, type, handle, wrapper)
    		obj.attachEvent("on" + type, wrapper);
    	}
    	else {
    		obj["on" + type] = handle;
    	}
    };
    

    看个例子:

    当点击前三个的时候会依次弹出classname,其他的都不会触发事件

    <style type="text/css">
    #out{ 500px;background-color: #CDE}
    #inner{background-color: #ABCDEF;margin: 0;padding: 0; 400px;}
    ul{background-color: pink;margin: 0;padding: 0; 400px;}
    li{398px;height: 20px;border: 1px solid black;margin: 15px 0px;padding: 0px;list-style: none;}    
    </style>
    div#out > div#inner :
    <div id="out">
    	<ul id="inner">
    		<li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    		<li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    		<li class="lib" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    		<li class="lib">class="lib"</li>
    		<li class="lib">class="lib"</li>
    		<li class="lib">class="lib"</li>
    	</ul>
    </div>
    ul :
    <ul>
    	<li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    	<li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    	<li class="lib" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
    	<li class="lib">class="lib"</li>
    	<li class="lib">class="lib"</li>
    	<li class="lib">class="lib"</li>
    </ul>
    
    <script>
    listeners = {
    	setWhat : function(opts) {
    		alert(opts.src.className);
    		return false;
    	},
    };
    window.onload = function(){$bindAction(document.getElementById('out'), ['click', 'mouseover'], listeners);}
    </script>
    

    效果如下:

    再看看事件的绑定情况,跟我们绑定事件的情况一致:


    微信号: love_skills

    越努力,越幸运!越幸运,越努力!

    做上CEO不是梦

    赢取白富美不是梦

    屌丝逆袭不是梦

    就是现在!!加油

  • 相关阅读:
    作一份高水准的简历
    使用该JavaBean可以将数据在JSP页面中以表格的形式显示出来,并具有动态排序 动态生成查询 自动分页功能
    javah命令 C Header and Stub File Generator
    Java内部类(Inner Class)
    集合(Collection)与迭代器(Iterator)
    Mysql数据库从本地导出 服务器上导入时报 ERROR 2005 HY000 Unknown MySQL ser
    Cassandra操作入门
    表示不同文件类型的魔术数字
    JAVA中實現鏈表--LinkedList的使用
    在oracle数据库中如何插入CLOB值
  • 原文地址:https://www.cnblogs.com/iforever/p/4532039.html
Copyright © 2011-2022 走看看