JS基础——事件绑定

上一篇博客JS事件对象中,老师问JS事件处理和VB中的事件处理有什么联系?先来解决一下这个问题。举个VB.net中事件处理的例子(JS敲久了,VB习惯的都不熟悉了,看来得经常回顾了):

1、事件处理VB VS JS

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        MsgBox("helo!")
        MsgBox(sender.width) '弹出触发这个事件对象的宽度
        MsgBox(sender.name) '弹出触发这个事件对象的名字
        MsgBox(TypeOf e Is Object) 'TRUE
        MsgBox(TypeOf sender Is Object) 'true
End Sub</span>

解析:看上面的事件处理代码:可以看出来组成和JS中的一模一样,同样包括触发事件的对象button1,事件处理函数Click和相应要执行的函数(这里理解为事件更好)Button1.Click(即要执行的行为),可见只是他们的表示方式有些不一样而已。

那么在这个事件处理中有两个参数sender和e,它们的作用又是干嘛的呢?

1、sender:触发事件的对象,这里指button,在代码中通过弹出sender.name来获取触发该事件对象的名字,sender.width来获取触发该事件对象的宽度等,可见通过sender可以获取触发该事件对象的相关信息。类型为object

2、e:这里看到e有没有觉得跟JS中事件绑定中传入的参数e有点儿一样呢?它在VB中就相当于JS中浏览器默认传递给事件处理的一个事件对象。通过e可以获取对应事件的相关信息,同样在上篇博客中通过JS中事件处理中的事件对象来获取一些事件的相关信息在VB中也是可以做到的,例如修改键的例子,在VB中通过e也是可以来进行判断用户按下的键值的,只是语法上不同罢了。同样它的类型为object

综上,JS中的事件处理和VB中的没啥区别(个人大胆的猜测中。。。),那么了解了事件对象后,对后面理解事件绑定会有很大的帮助。

二JS事件绑定

先理解一下事件绑定:其实,这里说到事件绑定,还是很熟悉,C#中用到的委托就是这么个思想,VB中也用到了事件绑定AddHandler,removeHandler等都是事件绑定思想的一个应用。核心思想都是讲一个方法或事件挂载到另一个事件或方法上去执行,调用时就好像一个代理,直接调用同一个事件或方法就可以执行规定好的同一种类型(或理解为遵循同一种规则)的所有方法或事件(纯属个人编造的句子)。

这里同一种规则在JS的事件绑定中可以理解为:比如同样都有一个触发事件的对象,后面紧跟着一个事件处理函数(onClick),在后面就是要执行的方法的具体过程等。

对于传统的事件绑定,JS中常见的有两种形式,内联和脚本样式,这种通常可以用来处理简单的事件函数,对于稍微复杂的,会有很大弊端:

1、不能同时绑定多个函数。

2、统一元素上多个相同的函数,不能够自动屏蔽相同的函数

3、函数体内的this指向window,而不是当前的DOM对象

4、函数执行的顺序不能按照绑定顺序执行

5、需要在函数体内进行标准化event对象

针对以上问题,JS中采取现代事件绑定,但W3C中直接采取现代事件绑定addEventListener可解决以上问题,IE中(attachevent)只能解决第一条和第5条。为了解决IE中this传递和标准化event问题,可以采用call传值的方式来解决。

	function addEvent(obj,type,fn){
		if ( typeof obj.addEventListener!='undefined'){ //W3C
			obj.addEventListener(type,fn,false);
		}else if(typeof obj.attachEvent!='undefined'){//IE
			obj.attachEvent('on'+type,function(){
				fn.call(obj,window.event);//利用对象冒充来解决this传递问题,window.event参数的传递用来解决标准化event的问题。
			});
		}
	}

通过以上现代事件绑定后,出现一个问题,由于采用call来进行对象冒充,导致后面封装时,删除不需要的函数时出现困难,主要原因是无法识别到底是要删除哪一个函数,如果为每个函数加上一个ID,删除时,只要指明要删除的ID就可以了。针对这个问题,我们在基于JS一切皆对象的原理上,可以为每一个事件添加一个属性ID,来进行识别。同时,针对于上述IE中出现的其余问题,采取了传统事件绑定来模拟现代事件绑定的方式来解决相同函数屏蔽和删除指定函数的问题。

1、模拟现代事件绑定

//为每个事件分配一个计数器
addEvent.ID=1; //为了防止全局变量的灾难,所以将事件ID变为addEvent的属性

function addEvent(obj,type,fn){
	if ( typeof obj.addEventListener!='undefined'){ //W3C
		obj.addEventListener(type,fn,false);
	}else {
		//创建一个存放事件的哈希表
		if(!obj.events)obj.events={};
		//第一次执行时执行
		if(!obj.event[type]){
			//创建一个存放事件处理函数的数组
			obj.events[type]=[];
			//把第一次的事件处理函数先存储到第一个位置
			if(obj['on'+type]) obj.events[type][0]=fn;
		}else {
		//同一个注册函数进行屏蔽,不添加到计数器中
			if(addEvent.equal(obj.events[type],fn)) return false; //如果之后的函数与第一个相等,自动屏蔽
		}
		//从第二次开始,用事件计数器来存储
		obj.events[type][addEvent.ID++]=fn;
		//执行事件处理函数
		obj['on'+type]=addEvent.exec(); //这里讲事件处理执行函数进一步封装
		}

}

2、封装事件处理的执行函数

	addEvent.exec=function(event){  //这里需要通过传递的事件来获取事件类型
		var e=event||addEvent.fixEvent(window.event); //通过addEvent事件中传递的event对象来获取type类型
		var es=this.events[e.type] //将obj用this来代替获取obj对象
		for (var i in  es){ //这里要用this.events[e.type],不能直接用obj.events
			es[i].call(this,e);  //IE需要传递this来弹出this.value值,解决IE中的this传递问题
		}
	}

3、同一个注册函数进行屏蔽

	addEvent.equal=function(es,fn){
		for(var i in es){
			if(es[i]==fn) return true;
		}
		return false;
	}

4、删除事件

	function removeEvent(obj,type,fn){
		if(typeof obj.removeEventListener!='undefined'){
			obj.removeEventListener(type,fn,false);
		}else {
			for (var i in obj.events[type]){
				if(obj.events[type][i]==fn){
					delete obj.events[type][i];
				}
			}
		}
	}

可以看出,IE在模拟现代事件过程中,事件对象e起了很大作用,通过它可以获取添加事件的类型及ID,而在删除时,正好借助于事件对象获取的属性来进行删除,很方便。同时,理解了跨浏览器事件绑定的封装,对后面JS封装库理解也就简单了很多,封装时,很多方法也都是在这个基础上来进行的,最后若想实现连缀,需要返回封装库的一个核心对象,这也是后面学习JQuery的一个核心。

以上纯属个人理解,不代表百度或CSDN的意见,若参考,请认真斟酌!



时间: 2024-10-08 03:16:25

JS基础——事件绑定的相关文章

js基础——事件绑定(事件监听)

JavaScript事件一共有三种监听方法分别如下: 1.事件监听一夹杂在html标签内 1 <div id="box" onClick="alert('HELLO WORLD')"> 2 <div id="box2" onClick="notice();"></div> 3 <div id="box3" onClick="service('HELLO W

笔记-[6]-js中事件绑定方法的总结

js中的两种对象事件绑定方法: 1:常用的如:div.onclick=function(){...}; 2:通过系统方法绑定事件: 非IE:addEventListener('事件名[不加on]',function(){},false[或者true]) IE:attachEvent('事件名[加on]',function(){}); 通过系统方法绑定事件可以让对象可以绑定相同的事件并且执行不同的操作,如果使用第一种方法绑定多个相同的事件,最后一个事件会覆盖前面所有的事件. 在addEventLi

JS中事件绑定的三种方式

以下是搜集的在JS中事件绑定的三种方式. 1. HTML onclick attribute <button type="button" id="upload" onclick="upload_file();"> 原文: http://www.w3school.com.cn/jsref/jsref_events.asp 2. jQuery .on() $(node).on("change", function(e)

JS基础——事件对象event

事件为什么会是对象呢?先了解一下事件处理 一.事件处理 JS在事件处理函数中提供了事件对象,帮助处理鼠标和键盘事件.同时还可以修改一些事件的捕获和冒泡流的函数. 事件处理分为三部分:对象.事件处理函数=函数 document.onclick=function(){ alert(this.value); //this代表着在该作用域中离它最近的对象. } 以上事件处理中,document为对象,click是事件处理类型,onclick为事件处理函数.function()为匿名函数,用于触发后执行.

JS的事件绑定、事件流模型

.t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.JS事件 (一)JS事件分类 1.鼠标事件:click/dbclick/mouseover/mouseout2.HTML事件: onload/onunload/onsubmit/onresize/onchange/onfoucs/onscroll3.键盘事件: keydown:键盘按下时触发 keypress:键盘按下并抬起的瞬间触发. keyup:键盘抬起触发[注意

JS中事件绑定

事件绑定 事件绑定 IE方式 attactEvent(事件名称,函数),绑定事件处理函数 derachEvent(事件名称,函数),解除绑定 DOM方式 addEventListener(事件名称,函数,捕获) removeEventListener(事件名称,函数,捕获) 绑定事件代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></titl

js元素事件绑定与解绑

为元素绑定事件有3种方式: 1.最常见的绑定方式: document.getElementById("btn").onclick=function(){}; 2.非IE浏览器     element.addEventListener(type,fn,false) (布尔值====true表示捕获,false表示冒泡,一般用false): document.getElementById("btn").addEventListener("click"

js基础-事件委托

让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行! <!DOCTYPE html> <html> <head> <title>事件委托</title> </head> <body> <ul id="ul"> <li class="item">11</li> <li class="item">22<

JS 基础事件的用法

// 1.9以上用on // 案例一 // $('#btn').on('click', function(){ // //console.log(1); // alert('测试...'); // }); // 案例二 // $('#btn').on('click mouseover', function(){ // //console.log(1); // alert('测试...'); // }); // 案例三 // $('#btn').on('mouseover mouseout', f