javascript----事件


事件处理程序在应用中是必不可少的,虽然现在很多框架都有自己实现事件处理方法,但是熟知原生才能让我们应对各种各样的需求并且实现自己的想法


事件流

这个是很基本很基本的概念了
DOM2级事件规定的事件流包括三个阶段:
①事件捕获阶段
②处于目标阶段
③冒泡阶段
并且明确要求捕获阶段不会涉及事件目标


事件处理程序

这里主要讲DOM2级事件处理程序,HTML事件处理程序和DOM0级事件处理程序现在几乎很少接触,故跳过

DOM2级事件处理程序

addEventListener()
接收三个参数:①要处理的事件名②事件处理程序③布尔值(true表示捕获阶段调用时间处理程序(建议),false表示冒泡阶段)
removeEventListenser()
接收的参数与addEventListener一样,需要注意的是,通过addEventListener()添加的匿名函数将无法通过removeEventListener()移除

IE事件处理程序

addEventListener在IE8及更早版本都不给予支持,但有类似的两个方法:attachEvent()detachEvent(),同样接收事件处理程序名称和事件处理程序函数作为参数,默认在冒泡阶段调用
注意:
①这里的时间处理程序名称没有on前缀
②这里的时间处理程序会在全局作用域中运行,故this等于window

跨浏览器的事件处理程序

var EventUtil = {
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }else if(elment.attachEvent){
            element.attachEvent("on"+type,handler);
        }else{
            element["on"+type] = handler;
               }
    },
    removeHandler:function(element,type,handler){
        if(element,removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent("on"+type,handler);
        }else{
            element["on"+type] = null;
        }
    }
}

事件对象

事件对象包含着所有与时间有关的信息,包括导致事件的元素、事件的类型以及其他与特定时间相关的信息.事件对象又分为DOM事件对象和IE事件对象,下面将分开总结

DOM中的事件对象

兼容DOM的浏览器会将一个event对象传入到事件处理程序中,event对象包含与创建它的特定事件有关的属性和方法,不同事件类型不一样,不过所有事件都有下列共同的属性和方法

  • bubbles 布尔值 表明事件是否冒泡
  • cancelable 布尔值 表明是否可以取消事件的默认行为
  • currentTarget 节点 其事件处理程序当前正在处理事件的那个元素
  • defaultPrevented 布尔值 是否被阻止了默认操作
  • detail Integer 与事件相关的细节
  • eventPhase Integer 调用事件处理程序的阶段:1->捕获 2->处于目标 3->冒泡
  • preventDefault() 取消事件的默认行为
  • stopImmediatePropagation() 取消事件的进一步捕获或冒泡同时阻止任何事件处理程序被调用(DOM3)
  • stopPropagation() 取消事件的进一步捕获或冒泡
  • target 节点 事件的目标
  • trusted 布尔值 是否为浏览器生成的
  • type 被触发的事件的类型
  • view 与事件关联的抽象视图

注意:在事件处理程序内部,对象this始终等于currentTarget,即相应事件的元素,而不一定是触发事件的元素,而event.target则指向触发事件的元素

IE中的事件对象

要访问IE中的event对象的方式取决于指定事件处理程序的方法:
①使用DOM0级添加事件处理程序时,event对象作为window对象的一个属性存在
②使用attachEvent()添加的事件处理程序,会有一次event传入事件函数中
③通过HTML特性制定的事件处理程序,可以通过一个叫event的变量来访问event对象

IE的event对象同样包含与创建它的事件相关的属性和方法,但所有事件对象都会包含下面所列的属性和方法

  • cancelBubble 布尔值 默认false,设置为true可以取消事件冒泡
  • returnValue 布尔值 默认true,但将其设置为false可以取消事件的默认行为
  • srcElement 事件的目标,与DOM中的target属性相同
  • type 被触发的事件的类型

跨浏览器的事件对象

var EventUtil = {
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }else if(elment.attachEvent){
            element.attachEvent("on"+type,handler);
        }else{
            element["on"+type] = handler;
               }
    },
    removeHandler:function(element,type,handler){
        if(element,removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent("on"+type,handler);
        }else{
            element["on"+type] = null;
        }
    },
    getEvent:function(event){
        return event? event: window.event;
    },
    getTarget:function(event){
        return event.target||event.srcElement;
    },
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault;
        }else{
            event.returnValue = false;
        }
    },
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble = true;
        }
    }
}

事件类型

UI事件

  • load

当页面完全加载后在window上触发,当图像加载完毕时在img元素上触发等

注意:对于新图像元素,只要设置了src属性就会开始下载,但script和link只有在把相关元素添加到文档后才会开始下载

  • unload

在文档被完全卸载后触发,利用最多的情况是清除引用,以避免内存泄漏

  • resize

当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件,建议在该事件的事件处理程序中不要加入大计算量的代码,因为会被频繁执行,从而导致浏览器反应变慢

  • scroll事件

发生滚动时触发,虽然在window对象上发生,但它实际表示的是页面中相应元素的变化,通常配合scrollLeft和scrollTop来使用

焦点事件

  • focus
  • blur

鼠标与滚轮事件

鼠标事件

  • click
  • dblclick
  • mousedown
  • mouseup
  • mouseenter 在鼠标从元素外部首次移动到元素范围之内触发
  • mouseleave 在位于元素上方的鼠标光标移动到元素范围之外时触发
  • mousemove 当鼠标指针在元素内部移动时重复地触发
  • mouseout 当鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发,又移入的另一个元素可能位于前一个元素的外部,也可能是这个元素的子元素
  • mouseover 在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内触发
  • mousewheel 当用户通过鼠标滚轮与页面交互、在垂直方向上滚动页面都会触发mousewheel事件

注意 除了mouseenter和mouseleave之外,所有鼠标事件都会冒泡

鼠标事件event特有属性

  • 客户区坐标位置:
    通过event.clientX和event.clientY来获取鼠标光标距离视口的位置
  • 页面坐标位置:
    通过event.pageX和event.pageY来获取鼠标光标距离页面的位置
  • 屏幕坐标位置
    通过event.screenX和event.screenY来获取鼠标光标距离屏幕的位置
  • 修改键
    鼠标可能会配合修改键使用,可以通过event.shiftKey,event.ctrlKey,event.altKey,event.metaKey的布尔值来获知对应的修改键是否按下了,从而给予正确的反馈事件
  • 相关元素
    在发生mouseover和mouseout事件时,会涉及到更多的元素
    ①mouseover: 主目标是获得光标的元素,相关元素是失去光标的元素
    ②mouseout: 主目标是失去光标的元素,相关元素是获得光标的元素
    DOM中,event.relatedTarget表示相关元素
    IE8之前,前者用event.fromElement,后者用event.toElement来表示相关元素
  • 鼠标按钮
    对于mousedown和mouseup事件,其event对象存在一个button属性,表示按下或释放的按钮,在DOM中,button属性有以下值
    0表示主鼠标按钮
    1表示中间按钮
    2表示次鼠标按钮
    在IE8及之前版本中也提供button属性,不过属性值与DOM有很大差异
    这里有跨浏览器方案:
    var EventUtil = {
  //省略了其他代码
   getButton:function(event){
    if(document.implementation.hasFeature("MouseEvents","2.0")){
        return event.button
    }else{
        switch(event.button){
            case 0:
            case 1:
            case 3:
            case 5:
            case 7:
                return 0;
            case 2:
            case 6:
                return 2;
            case 4:
                return 1;
        }
    }
    },
     //省略了其他代码
    };

鼠标滚轮事件
mousewheel的event对象除包含鼠标事件的所有标准信息外,还包含一个特殊的wheelDelta属性(IE,Opera,Chrome,Safari), detail属性(Firefox)
在wheelDelta
向前滚动:wheelDelta是120的倍数
向后滚动:wheelDelta是-120的倍数
在detail
向前滚动:detail的值是3的倍数
前后滚动:detail的值是-3的倍数
此处有跨浏览器方案:
var EventUtil = { //省略了其他代码 getWheelDelta:function(event){ if(event.wheelDelta){ return(client.engine.opera&&client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); }else{ return -event.detail * 40; } } }

键盘与文本事件

有三个键盘事件和一个文本事件

  • keydown: 当用户按下键盘上任意键时触发,按住不放则连续触发
  • keypress: 当用户按下键盘上字符键时触发,按住不放则连续触发
    (Safari3.1之前的版本在按下非字符键时也会触发
  • keyup: 当用户释放键盘上的键时触发
  • textInput: 在文本插入文本框前会触发textInput事件,用意是将文本显示给用户之前更容易拦截文本

键盘事件event特有属性

  • 键码
    在发生keydown和keyup事件时,event对象的keyCode属性会包含一个代码与对应的按键对应
  • 字符编码
    发生keypress事件意味着按下的键会影响到屏幕中文本的显示,因此在所有浏览器中,按下能够插入或删除字符的键都会触发keypress事件

变动事件

  • DOMSubtreeModified:在DOM结构中发生任何变化时触发
  • DOMNodeInserted:在一个节点作为子节点被插入另一个节点时触发
  • DOMNodeRemoved: 在节点从其父节点中被移除时触发
  • DOMNodeInsertedIntoDocument:在一个节点被直接插入文档或通过子树间插入文档之后触发
  • DOMNodeRedmovedFromDocument:同理
  • DOMAttrModified:在特征被修改之后触发
  • DOMCharacterDataModified:在文本节点的值发生变化时触发

HTML5事件

  • contextmenu:单机鼠标右击事件
  • beforeunload:在浏览器卸载页面之前触发
  • DOMContentLoaded:在页面中的一切都加载完毕时触发,在形成完整的DOM树之后就会触发,不理会图像、js文件等资源是否下载完毕
  • readystatechange
    这个事件的目的时提供与文档或元素的加载状态有关的信息,支持此事件的每个对象都有一个readyState属性
  • pageshow和pagehide事件(Firfox opera)
  • hashchange:在URL的参数列表发生改变时触发

设备事件(略)

触摸与手势事件

触摸事件
  • touchstart:当手指触摸屏幕时触发
  • touchumove:当手指在屏幕上滑动时连续地触发
  • touchend:当手指从屏幕上移开时触发
  • touchcancel:当系统停止跟踪触摸时触发
    除了常见的DOM属性外,触摸事件还包含下列三个用于跟踪触摸的属性:
    (1)touches:表示当前跟踪的触摸操作的Touch对象的数组
    (2)targetTouchs:特定与事件目标的Touch对象的数组
    (3)changeTouched:表示自上次触摸以来发生了什么变化的Touch对象的数组
手势事件
  • gesturestart:当一个手指已经按在屏幕上而另一个手指又触摸屏幕时触发
  • gesturechange:当触摸屏幕的任何一个手指的位置发生变化时触发
  • gestureend:但任何一个手指从屏幕上面移开时触发。
    注意:在一个元素上设置事件处理程序,意味着两个手指必须同时位于该元素的范围之内,才能触发手势事件(这个元素就是目标),由于这些事件冒泡,所以将事件处理程序放在文档上也可以处理所有手势事件,此时事件的目标就是两个手指都位于其范围 内的那个元素。
    特殊属性:
  • rotation:表示手指变化引起的旋转角度,负值表示逆时针旋转
  • scale:表示两个手指尖距离的变化情况,这个值从1开始,并随距离拉大而增长,随距离缩小而减小

内存和性能

事件委托

事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件

EventUtil.addHandler(document,'click',function(event){
    event = EventUtil.getTarget(event);
    switch(target.id){
     case "dosomething":
             handleDosomething()
             break;
     case "goSomewhere":
            handleGosomgwhere()
            break;
  }
});

事件委托的优点:

  • document对象很快就可以访问,而且在页面生命周期的任何时点上为它添加事件处理程序。换句话说,只要可点击的元素呈现在页面上,就可以立刻具备适当的功能。
  • 在页面中设置事件处理程序所需的时间更少,只添加一个事件处理程序所需的DOM引用更少,所花的时间也更少。
  • 整个页面占用的内存空间更少,能够提升整体性能

模拟事件

DOM中的事件模拟
  • ①document.createEvent()创建一个event对象,可接受一个参数,表示要创建的事件类型的字符串(UIEvetnts,MouseEvents,MutationEvents,HTMLEvents)
  • ②创建的event对象都对应有一个特殊的初始化方法,传入适当的数据可以初始化该evnet对象
  • ③在DOM节点上使用dispatchEvent()方法触发这个事件
自定义事件

自定义事件不是由DOM原生触发的额,它的目的是让开发人员创建自己的事件。

  • ①调用document.createEvent('CustomEvent')创建一个自定义事件对象,有一个名为initCustomEvent()的方法接收以下4个参数:
    • type(字符串):触发的事件类型
    • bubbles(布尔值):表示时间是否应该冒泡
    • cancelable(布尔值):表示事件是否可以取消
    • detaitl(对象):任意值,保存在event对象的detail属性中
  • ②在对应节点上绑定该事件
  • ③使用dispatchEvent(event)事件触发。

此处跳过对IE的事件模拟。

以上参考红宝书《高程三》
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 事件流 事件流描述的是从页面中接受事件的顺序。但是IE和Netscape开发团队提出了差不多相反的事件流的概念。I...
    losspm阅读 263评论 0 0
  • 一、事件流 1.1 事件流 事件流:从页面中接受事件的顺序 事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最...
    范小饭_阅读 1,063评论 1 9
  • JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发...
    劼哥stone阅读 1,252评论 3 11
  • 事件基本概念 事件类型:用来说明发生什么类型事件的字符串,即事件名。事件目标:发生事件的对象。当谈论事件时,会同时...
    留七七阅读 1,021评论 0 11
  • 人生如戏,戏如人生。在各自前进的路上,你会遇见许多人,许多故事,许多风景。幸福的是,奔跑从未停止。你就要相...
    未及风深阅读 1,933评论 1 3