博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript中事件处理
阅读量:6814 次
发布时间:2019-06-26

本文共 3830 字,大约阅读时间需要 12 分钟。

原文:

先看看下面一道题目,请评价以下代码并给出改进意见:

if (window.addEventListener) {
//标准浏览器 var addListener = function(el, type, listener, useCapture) { el.addEventListener(type, listener, useCapture); };} else if (document.all) {
//IE addListener = function(el, type, listener) { el.attachEvent("on" + type, function() { listener.apply(el); }); }}

1)不应该在if和else语句中声明addListener函数,应该先声明;

2)不需要使用window.addEventListener或document.all来进行检测浏览器,应该使用能力检测;

3)attachEvent在IE中有this指向问题,会指向window,虽然上面的代码做了指向处理,但是匿名函数不能做detachEvent解绑

改进后的代码稍后加上。

 

一、冒泡与捕获

使用过方法的会发现最后一个参数“useCapture”,用于控制是捕获还是冒泡。

何为冒泡、捕获,请看下面的例子:,在线代码中用了三层。

事件

1)Netscape主张元素1的事件首先发生,这种事件发生顺序被称为捕获型,如下图所示:

| |---------------| |-----------------| click1       | |                ||   -----------| |-----------     ||   |click2    \ /          |     ||   -------------------------     ||        Event CAPTURING          |-----------------------------------

2)微软则保持元素2具有优先权,这种事件顺序被称为冒泡型,如下图所示:

/ \---------------| |-----------------| click1       | |                ||   -----------| |-----------     ||   |click2    | |          |     ||   -------------------------     ||        Event BUBBLING           |-----------------------------------

3)W3C选择了一个择中的方案。任何发生在w3c事件模型中的事件,首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段,如下图所示:

| |  / \---------------| |--| |------------| click1       | |  | |           ||   -----------| |--| |------     ||   |click2    \ /  | |     |     ||   -------------------------     ||      W3C event model            |-----------------------------------

4)阻止冒泡,很多时候是不想触发父级的相同事件的,那么就需要阻止这种行为。

W3C方:event.()。(chrome、firefox、safrai等)

IE方:event.设置为true。

经过我的在线测试,stopPropagation这个方法不能阻止捕获。

这里顺带说下阻止默认事件的方法,何为默认事件?就比如a标签设置了href,就会做跳转,这里阻止它跳转。

W3C方:event.(),但只有event的cancelable属性为true时才能使用。

IE方:event.设置为false。

 

二、事件系统

浏览器提供了3种层次的API。

1)最原始的是写在元素标签内

2)以el.onXXX=function绑定的方式,通称为DOM0事件系统。

3)一个元素的同一类型事件可以绑定多个回调,通称为DOM2事件系统。

IE与W3C依旧不同,语法如下:

序号  操作与对象 IE方 W3C方

1

绑定事件

el.("on"+type, callback) el.(type,callback,[useCapture])

2

卸载事件

el.("on"+type,callback) el.(type,callback,[useCapture])
3 创建事件 document.()

document.(types) 创建事件

event.() 初始化事件

4

派发事件

el.(type,event) el.(event)
5 event属性

currentTarget:其事件处理程序当前正处理事件的元素

target:事件的目标

srcElement:等于target,默认目标
6 event方法

preventDefault():阻止默认行为

stopPropagation():阻止冒泡

returnValue:等于preventDefault()

cancelBubble:设为true等于stopPropagation()

7

type

被触发的事件类型,需要“on”前缀 被触发的事件类型

8

事件执行顺序

与添加顺序相反 与添加顺序一致
9

匿名函数

无法移除 无法移除

10

this

window 当前绑定的元素

 

注意第8点,在测试代码中,我绑定了两个相同的“click”事件,

var func1 = function(e) {  alert(1); //测试执行顺序};var func2 = function(e) {  alert(2);};var type = 'click';bind(ele, type, func1);bind(ele, type, func2);

在IE中先弹出2,再弹出1。而在chrome中先弹出1,再弹出2。

 

注意上面的第9点和第10点,上面那道题目中要解决的就是这个问题。下面的代码是个片段,

var bind = function(ele, type, callback) {  if (!ele[type + "event"]) {    ele[type + "event"] = {}; //声明一个空对象,缓存事件  }  var name = callback.toString();  if (!ele[type + "event"][name]) {    var handler = function(event) {      //可以做更多event封装操作      var ev = event || window.event;      callback.call(ele, ev);    };    ele[type + "event"][name] = handler; //做个临时变量  }  if (ele.addEventListener) {    ele.addEventListener(type, handler, false);  } else if (ele.attachEvent) {    ele.attachEvent('on' + type, handler);  }}var unbind = function(ele, type, callback) {  var handler = ele[type + "event"][callback.toString()]; //读取临时变量  if (ele.removeEventListener) {    ele.removeEventListener(type, handler);  } else if (ele.detachEvent) {    ele.detachEvent('on' + type, handler);  }}

上面的代码还比较粗糙,仅仅是用于演示一下。方法有很多,自己可以揣摩。

我看到网上有人直接不用attachEvent,将相应的事件保存在一个数组中,当detachEvent的时候做splice数组的操作。

大家也可以参考下一些成熟的类库,例如版本,2642行的event.add封装,2757行的event.remove封装,3485行的on封装。

也可以参考Dean Wdwards写的方法,这是Prototype时代早期出现的一个事件系统,jQuery事件系统的源头。

 

参考资料:

   前端事件系统(一)

    JavaScript要点归档:事件

    生动详细解释javascript的冒泡和捕获

    解决attachEvent中this指向问题

转载地址:http://huczl.baihongyu.com/

你可能感兴趣的文章
DataTable数据存入指定路径的Excel文件
查看>>
Linq-C#左连接
查看>>
c和指针读书笔记
查看>>
常用正则表达式集锦
查看>>
JS 验证
查看>>
【Lua】特性和一些基础语法
查看>>
Jaxb2 实现JavaBean与xml互转
查看>>
shell中exec解析(转)
查看>>
ContentType ,charset和pageEncoding的区别(转)
查看>>
21副GIF动图让你了解各种数学概念(转。太强大了)
查看>>
SQL Server 2008通过LinkServer连接MySQL
查看>>
模板:LCT
查看>>
mysql的数据类型int、bigint、smallint 和 tinyint取值范围 及varchar
查看>>
[android] 手机卫士自定义控件的属性
查看>>
Java自定义类加载器与双亲委派模型
查看>>
jQuery初步
查看>>
过滤器详解
查看>>
程序员必看
查看>>
Outlook 快速邮件清理
查看>>
Java动态代理(一)动态类Proxy的使用
查看>>