JavaScript 事件注册

事件注册

事件注册有哪些方法

on + “event”

例如:onclick/onmouseover…支持最广。但是要在一个元素上多次添加同一事件,此时就无能为力了,只能以最后一次绑定的事件为准。

addEventListener

W3C 标准方法,功能也最强大,支持添加多个事件

//element.addEventListener(type,listener,useCapture);
obj.addEventListener('click', method1, false)
obj.addEventListener('click', method2, false)
obj.addEventListener('click', method3, false)

执行顺序为 method1 -> method2 -> method3,第三个参数是指以“冒泡”还是“捕获”的标准绑定事件,一般为false(冒泡)。

并且可以使用 removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄。

事件句柄:又称事件处理函数 event handlers

  1. 指事件发生时要进行的操作。
  2. 将相应的函数或语句指定给事件句柄,则在该事件发生时,浏览器便执行指定的函数或语句,从而实现网页内容与用户操作的交互。

注意:如果要移除事件句柄,addEventListener() 的执行函数必须使用外部函数,如上述实例所示(method 1/2/3)。

匿名函数,类似“windows.removeEventListener(“event”,function(){ myScript});”该事件是无法移除的。

如果浏览器不支持 removeEventListener() 方法,你可以使用 detachEvent() 方法实现。

var x = window.getElementById('myDIV')
if (x.removeEventListener) {
	// 所有浏览器,除了 IE 8 及更早IE版本
	x.removeEventListener('mousemove', myFunction)
} else if (x.detachEvent) {
	// IE 及更早IE版本
	x.detachEvent('onmousemove', myfunction)
}

attachEvent

IE 家的方法,火狐与其他家浏览器都不支持,attachEvent——兼容:IE7、IE8;不兼容 firefox、chrome、IE9、IE10、IE11、safari、opera.尽量不要用,支持绑定多个事件,与 addEventListener()执行顺序相反,即 method3->method2->method1

进行兼容性处理

1. 简单通过 if 判断

if (window.addEventListener) {
	// 功能最强大
	div.addEventListener('click', function() {
		alert('hello, world')
	})
} else if (window.attachEvent) {
	// 非标准特性 尽量不要使用
	div.attachEvent('click', function() {
		alert('hello, world')
	})
} else {
	// 支持度最好
	div['onclick'] = function() {
		alert('hello, world')
	}
}

2. 封装成函数

function registeEvent(el, type, handler, useCapture) {
	if (window.addEventListener) {
		// 功能最强大
		el.addEventListener(type, handler, useCapture)
	} else if (window.attachEvent) {
		// 非标准特性 尽量不要使用
		el.attachEvent(type, handler)
	} else {
		el['on' + type] = handler
	}
}

到这里,我们每次注册事件时都通过 registeEvent 注册,很明显,每次注册都要判断浏览器的能力是否支持,每一次都要检测,这不是我们想要的。

3. 使用立即执行函数进行优化

var registeEvent = (function creatEventRegister() {
	if (window.addEventListener) {
		return function(el, type, handler, useCapture) {
		el.addeventListener(type, handler, useCapture)
		}
	} else if (window.attachEvent) {
		return function(el, type, handler) {
			el.attachEvent(type, function() {
				handler.call(el, window.event) // 注:attachEvent内部this指向window而不是触发对象,使用call方法修改this
			})
		}
	} else {
		return function(el, type, handler) {
			el['on' + type] = handler
		}
	}
})()

call() 方法第一个参数覆盖函数里的 this, 第二个参数作为函数的函数传进去

此后只用通过 registeEvent 方法注册事件即可,且只在最开始的时候进行一次能力检测。

registeEvent(divm 'click', function() {
	alert('hello world')
})

此时依旧存在一个缺点,如果我们从头到尾没有绑定过事件,即使用 registerEvent 函数,那么立即执行函数白白执行了一次完全是多余的,我们可以使用惰性载入函数来进行优化。

4. 惰性载入函数方案

此时 registerEvent 依然被声明为一个普通函数,在函数里依然有一些分支判断。但是在第一次进入条件分支后,在函数内部会重写这个函数,重写之后的函数就是我们期待的 registerEvent 函数,在下一次进入 registerEvent registerEvent 函数里不再存在条件分支语句:

var registerEvent = function(el, type, handler, useCapture) {
	if(window.addEventListener) {
	 	registerEvent = function(el, type, handler, useCapture) {
	 		el.addEventListener(type, handler, useCapture)
	 	}
	} else if (window.attachEvent) {
		registerEvent = function(el, type, handler) {
	 		el.attachEvent(type, handler) {
	 			handler.call(el, window.event)
	 		}
	 	}
	} else {
		registerEvent = function(el, type, handler) {
	 		el['on' + type] = handler
	 	}
	}
}

阿里笔试题

 if (window.addEventListener) {
        var addListener = function(el, type, listener, useCapture) {
            el.addEventListener(type, listener, useCapture);
        };
    } else if (document.all) {
        addListener = function(el, type, listener) {
            el.attachEvent("on" + type, function() {
                listener.apply(el);
            });
        };
    }

请阐述 :

a) 代码的功能;

b) 代码的优点和缺点;

c) listener.apply(el) 在此处的作用;

d) 如果有可改进之处,请给出改进后的代码,并说明理由。

参考答案:

a) 功能:事件注册
b) 优点:跨浏览器,特性探测,性能优化。缺点:document.all
c) 作用:使得IE中listener的this 为 el,与其它浏览器一致
d) 改进:document.all改成window.attachEvent; useCapture的默认
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值