js中事件详解

js事件

Posted by tinypoint on October 7, 2017

本文首次发布于 tinypoint`s blog, 作者 @张小点(tinypoint) ,转载请保留原文链接.

前言

本文带我们去回顾js中事件的相关知识

事件流

“DOM2级事件”规定事件流包括三阶段:

  • 事件捕获阶段(不具体到具体)
  • 目标阶段
  • 事件冒泡阶段(从具体到不具体)

处于目标阶段,事件发生,在事件处理中被算作冒泡阶段的一部分。

“DOM2级事件”明确要求捕获阶段不会涉及事件目标,但是IE9,Safari,Chrome,Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。<p style="text-align:right">–JavaScript高级程序设计(第3版)</p>

事件处理程序(事件监听)

html事件监听

利用html属性,on + 事件名小写,值为js表达式,或一个函数,可接受一个event参数,函数内this指向事件的目标元素

<button onclick="clickMe()">click me</button>

DOM0级事件监听

var btn = document.getElementById('btn');
// 添加
btn.onclick = function () {
    alert('Hi');
}
// 删除
btn.onclick = null;

DOM2级事件监听

addEventListener, reomveEventListener 接受三个参数:事件名,事件处理函数,表示在什么阶段调用处理程序的布尔值,true表示在捕获阶段,false在冒泡阶段,一般用false

function fn () {
    alert('Hi');
}

var btn = document.getElementById('btn');
// 添加
btn.addEventListener('click', fnfalse) 
// 可以添加多个,但是匿名函数不能通过removeEventListener移除
btn.addEventListener('click', function() {alert('Hello')}, false);
// 删除
btn.removeEventListener('click', fn, false);

兼容各个浏览器的事件处理程序

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

事件对象

DOM中的事件对象

  • bubbles是否冒泡
  • cancelable是否可以取消默认行为
  • currentTarget你注册事件的那个元素,函数内this始终等于currentTarget
  • target触发事件的实际元素
  • defaultPrevented是否调用了preventDefaul()
  • detail事件相关的细节信息
  • eventPhase事件的阶段,1-2-3分为对应捕获-目标-冒泡
  • preventDefault()取消默认事件
  • stopImmediatePropagation()取消捕获或冒泡,同时阻止任何事件
  • stopPropagation()取消捕获或冒泡
  • trustedtrue表示是浏览器生成的,false表示是开发人员注册的
  • view事件发生的视图,指向window

IE中的事件对象

DOM0级的event被保存在window.event中,DOM2级的event会被当做参数传入

  • cancelBubble默认为false,为true代表可以取消事件,类似stopPropagation()
  • returnValue默认为true,为false表示取消默认,类似preventDefault()
  • srcElement等同target

事件类型

UI事件

1.load

  • window
  • img 指定src就开始下载。
  • script
  • linkscript一样,指定了src或者href而未插入到文档中,不会开始下载。

2.unload

文档一切都卸载之后触发,一般用于引用清除,以避免内存泄漏。

要小心使用unload事件,因为页面的对象就不存在了。

貌似Chrome不支持onunload事件,IE支持。

3.resize

几个简单的获取窗口宽高的方法:

  • document.body.clientWidth
  • document.body.offsetWidth
  • document.body.scrollWidth

4.scroll

  • scrollTop
  • scrollLeft

焦点事件

  1. blur失焦触发,不会冒泡,所有浏览器支持

  2. focusout失焦触发,冒泡,IE5.5+,Safari5.1+,Opera11.5+,Chrome支持

  3. focus获得焦点触发,不会冒泡,所有浏览器支持

  4. focusin获得焦点触发,冒泡,IE5.5+,Safari5.1+,Opera11.5+,Chrome支持

鼠标与滚轮事件

  1. click(mousedown > mouseup > click)
  2. dobuleclick(两个click)
  3. mousedown
  4. mouseup
  5. mouseenter(不冒泡)
  6. mouseleave(不冒泡)
  7. mouseout
  8. mouseover
  9. mousemove

mouseentermouseleave相比较mouseovermouseout,前二者不冒泡,后二者冒泡

  • 修改键 event.shiftKeyevent.ctrlKeyevent.altKey,event.metaKey
  • 屏幕坐标 screenXscrrenY
  • 浏览器视口坐标clientXclientY
  • 页面坐标pageXpageY

IE8之前不支持页面坐标,可以通过client和scroll换算出来

function getPageXAndY (event) {
    var pageX = event.pageX;
    var pageY = event.pageY;
    
    if (pageX === undefined) {
        pageX = event.clientX + (docuemnt.body.scrollLeft || document.documentElement.scrollLeft);
        pageY = event.clientY + (docuemnt.body.scrollTop || document.documentElement.scrollTop);
    }
    
    return {
        pageX: pageX,
        pageY: pageY
    }
}
  • mouseovermouseout特有事件对象属性relatedElement(其他事件该值为null),IE8之前不支持,有类似的fromElementtoElement

  • 鼠标按钮,事件对象的button属性,0主鼠标按钮,1中间按钮,2次鼠标按钮,IE有更多的button属性

  • 其他事件信息

altLeft,ctrlLeft,offsetX,offsetY,shiftLeft

  • 滚轮事件

参考