JavaScript学习笔记(12)

来源:互联网 发布:js offsettop 不准确 编辑:程序博客网 时间:2024/06/10 21:15

事件

JS与HTML之间通过事件进行交互。之前的jQuery笔记总结过事件的相关内容,很多重复的东西就省略掉了。事件相关的API很冗杂,很多东西可以即用现查,但基本的核心和概念还是需要掌握的。


1 事件流

事件流其实就是用于描述从页面接收事件的顺序。IE提出了从具体到宽泛的事件冒泡,网景提出了从宽泛到具体的事件捕获。DOM则集成了两家的特点,将事件流划分成三个阶段:

  • 事件捕获阶段,为截获事件提供机会
  • 处于目标阶段,实际的目标接收到事件
  • 事件冒泡阶段,对事件作出响应

2 事件处理程序

事件是用户或浏览器自身执行的某种动作(例如,单击:click,加载:load)。
事件处理程序是响应具体事件的函数(例如,单击处理事件:onclick)。


2.1 HTML事件处理程序

所谓HTML事件处理程序,即在HTML当中直接插入事件监听器。

<input type="button" value="Click" onclick="alert('clicked');">

由于HTML事件处理程序,行为和样式耦合紧密,不利于阅读和修改,所以不应当使用这种方法。


2.2 JavaScript事件处理程序

2.2.1 DOM0级事件处理程序

将一个函数赋值给一个事件处理程序,因为其操作简单可以跨浏览器而一直沿用至今,要使用JS事件处理程序需要先取得要操作对象的引用。

var btn = doucment.getElementById("mybtn");btn.onclick = function(){    alert("this.id");};btn.onclick = null;

DOM0级事件处理程序只有被执行之后,才会和被监听的元素绑定。
DOM0级事件处理程序是属于被监听元素的方法,其中的this就是被监听元素的引用。
将事件处理程序赋值为null,即可删除该方法。


2.2.2 DOM2级事件处理程序

DOM2添加了用于绑定和删除事件处理程序的操作:

  • addEventListener(eventName,eventFunction,boolean)
  • removeEventListener(eventName,eventFunction,boolean)

布尔值为true,表示在捕获阶段调用事件处理程序
布尔值为false,表示在冒泡阶段调用事件处理程序

var btn = document.getElementById("myBtn");var handler = function(){    alert(this.id);};btn.addEventListener("click",handler,false);btn.removeEventListener("click",handler,false);

为同一元素绑定多个事件处理程序,则它们会按照顺序触发。
removeEventListener()的参数要和addEventListener()的参数一致才可以删除。
通常情况下,都是讲事件处理程序添加到冒泡阶段,以最大限度地兼容各类浏览器。


2.2.3 IE事件处理程序

IE的事件处理与其他浏览器不同,IE实现了类似的方法:

  • attachEvent(eventName,eventFunction)
  • detachEvent(eventName,eventFunction)
var btn = document.getElementById("myBtn");btn.attachEvent("onclick",function(){    alert("something")});

IE的事件处理程序中this指向全局(window),而不是DOM中的被监听元素。
IE下,一个元素绑定了多个事件处理程序,会逆序执行,后定义的先执行。
移除方法的时候参数也要和添加的时候一样。


2.3 跨浏览器实现事件处理程序

通常使用JavaScript库可以实现这一目的,不过如果需要自己实现细节内容,则需要考虑浏览器的能力检测。

var EventUtil = {    addHandler : function(ele,type,handler) {        if(ele.addEventListener){ //DOM2级            ele.addEvebtListener(type,handler,false);        } else if(ele.attachEvent){ //IE            ele.attachEvent("on"+type,handler);        } else { //DOM0级            ele["on"+type] = handler;        }    },    removeHandler : function(ele,type,handler) {        if(ele.removeEventListener){ //DOM2级            ele.removeEvebtListener(type,handler,false);        } else if(ele.detachEvent){ //IE            ele.detachEvent("on"+type,handler);        } else { //DOM0级            ele["on"+type] = null;        }    }};

3 事件对象

3.1 DOM中的事件对象

在触发DOM上的某个时间的时候会产生一个事件对象event,包含了所有与事件有关的信息(导致事件的元素,事件的类型,其他与特定事件相关的信息)。
event对象包含的属性和方法因事件类型不同而存在差异,公有的属性和方法如下(都是只读的):

名称 类型 说明 bubbles Boolean 表明事件是否冒泡 stopPropagation() Function 取消事件的进一步捕获或者冒泡,bubbles为true才能调用 stopImmediatePropagation Function 取消事件的进一步捕获或者冒泡,组织任何事件处理程序被调用 cancelable Boolean 表明是否可以取消事件的默认行为 preventDefault() Function 取消事件的默认行为,需要cancelable为true才能调用 defaultPrevented Boolean true表示已经调用了preventDefault() currentTarget Element 事件处理程序正在处理的元素,this始终指向该值 target Element 事件的目标 type String 被触发的事件的类型 detail Integer 与事件相关的细节信息 eventPhase Integer 调用事件处理程序的阶段(1:捕获阶段,2处于目标阶段,3:冒泡阶段) view AvstractView 发生事件的window对象

3.2 IE中的事件对象

IE的event对象在不同的事件处理方法中有所区别。
不同事件触发的event公有的属性如下:

名称 类型 说明 cancelBubble Boolean 默认为false,设置为true之后可以取消事件冒泡 returnValue Boolean 默认为true,设置为false之后可以取消事件的默认行为 srcElement Element 事件的目标(DOM中的target),IE下慎用this type String 被触发的事件类型

3.3 跨浏览器实现事件对象

继续2.3的例子,继续扩充兼容的实现方法:

var EventUtil = {    getEvent : function(event){        return event ? event : window.event; //window.event是IE的方法       },    getTarget : function(event){        return event.target||event.srcElement; //短路运算符      },    prevantDefault : function(event){        if(event.prevantDefault){            event.prevantDefault();         } else {            event.returnValue = false;          }    },    stopPropagation : function(event){        if(event.stopPropagation){            event.stopPropagation();            } else {            event.cancelBubble = true;          }    }};

4 事件类型

DOM3规定了以下几类事件:

  • UI事件,用户与页面上的元素交互时触发
  • 焦点事件,当元素获得或失去焦点时触发
  • 鼠标事件,当用户通过鼠标在页面上执行操作时触发
  • 滚轮事件,当使用鼠标滚轮时触发
  • 文本事件,当在文档中输入文本时触发
  • 键盘事件,当用户通过键盘在页面上执行操作时触发
  • 合成事件,当为输入法编辑器输入字符时触发
  • 变动事件,当底层的DOM结构发生变化时触发

4.1 UI事件

事件名称 描述 load 当页面完全加载后在window上触发
当所有框架都加载后在框架集上触发
当图像加载后在<img>元素上触发
当嵌入的内容完全加载后在<object>元素上触发 unload 与load相反,当卸载完成之后触发 abort 当用户停止下载过程时,如果没有加载完,则在<object>元素上触发 error 当JS错误或加载失败的情况下触发 select 当用户选择文本框中的字符时触发 resize 当窗口或框架的大小发生变化时触发 scroll 当滚动带有滚动条的元素是在该元素上触发,<body>元素中包含所加载页面的滚动条

4.2 焦点事件

事件名称 描述 focus 获得焦点时触发,不冒泡 blur 失去焦点时触发,不冒泡 focusin 获得焦点时触发,会冒泡 focusout 失去焦点时触发,会冒泡

4.3 鼠标&滚轮事件

事件名称 描述 click 在用户单击鼠标左键或按下回车时触发 dblclick 在用户双击左键后触发 mousedown 在用户按下任意鼠标按钮之后触发 mouseup 在用户释放鼠标按钮时触发 mouseenter 在鼠标光标从元素外部首次移动到元素范围内时触发,不会冒泡,移动到后代元素上不会触发 mouseleave 在位于元素上方的鼠标光标移动到元素范围之外时触发,不会冒泡,移动到后代元素上不会触发 mousemove 当鼠标指针在元素内部移动时重复触发 mouseout 在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发,无论另一个元素是后代元素还是外部元素都会触发 mouseover 在鼠标指针位于一个元素外部,用户将其首次移入一个元素边界之内时触发 mousewheel 跟踪鼠标滚轮

4.3.1 定位鼠标

事件名称 描述 clientX clientY 保存了鼠标相对于浏览器窗口左上角的位置。 pageX pageY 保存了鼠标相对于页面左上角的位置(如果有滚动,该值和clientX是有差异的) screenX screenY 保存了相对于显示器左上角的位置 shiftKey、ctrlKey、altKey、metaKey 监听按下鼠标时,对应的键是否被按下 relatedTarget 对于mouseover和mouseout时间,该值非null,而是表示了与时间相关的元素(例如,鼠标从A移入B,A上会触发mouseout,而相关元素就是B) button 监听鼠标哪个键被按下

4.4 键盘&文本事件

事件名称 描述 keydown 当用户按下键盘上的任意键时触发,按住不放会一直触发 keypress 当按下字符键时触发,按住不放会一直触发 keyup 释放任意键时触发 textInput 文本插入文本框之前会触发(DOM3级事件新加的事件)
包含属性data用于显示输入的文本,
inputMethod属性用于表示文本输入的方式(键盘、粘贴、拖放、表单选择、语音、手写)

4.5 复合事件&变动事件

复合事件,IME(输入法编辑器)输入的序列,类似于软键盘等物理键盘上找不到的字符,在输入的时候会触发这一类事件。
compositionstartcompositionupdatecompositionend分别对应了打开IME、输入字符、关闭IME的过程。和文本事件比较类似。

变动事件在DOM结构发生改变时会触发。


4.7 触摸&手势事件

移动端的设备由于其硬件的特殊性,人机交互与PC端也有所不同。

事件名称 描述 touchstart 当手指触摸屏幕时触发,多点触控的话会触发多次 touchmove 当手指在屏幕上滑动时连续触发,在这个事件发生期间用preventDefault()可以阻止滚动 touched 当手指从屏幕上移开时触发 touchcancel 当系统停止跟踪触摸时触发 gesturestart 当一个手指已经触摸屏幕,而另一个手指又触摸屏幕时触发 gesturechange 当触摸屏幕的任何一个手指位置变化时触发 gestureend 当任何一个手指从屏幕上移开时触发

每个触摸事件的event对象都提供了在鼠标事件中常见的属性(定位属性,按键属性等),除此之外,还有几个特有的用于跟踪触摸的属性:

  • touches:表示当前跟踪的触摸操作的Touch对象数组
  • targetTouches:特定于事件目标的Touch对象数组
  • changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。

Touch对象包含标识ID(identitier)、定位属性(clientX/Y,pageX/Y,screenX/Y)、DOM节点目标(target)

手势事件包含了触摸事件的属性并额外有表示手指变化引起的旋转角度的rotation属性和表示两指距离的scale属性。


5 模拟事件

JS可以模拟事件的触发,极大的方便了开发和测试。


5.1 DOM中的事件模拟

在document对象上使用createEvent()可以创建event对象,该方法的参数时要创建的事件类型的字符串,对应的init方法用于初始化事件,dispatchEvent()可以触发事件。

//模拟鼠标事件var btn = document.getElementById("mybtn");var event = document.createEvent("MouseEvents");event.initMouseEvent("click",true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null);btn.dispatchEvent(event);

5.2 IE中的事件模拟

与DOM的思路类似,document.createEventObject()(不带任何参数)创建事件对象,返回一个通用的event,手工对event添加必要信息,fireEvent()触发事件。


6 内存和性能

为了提高页面运行的性能,可以采取一些降低内存占用的手段。


6.1 事件委托

事件委托可以解决事件处理程序过多的问题,将所有的click事件整合到一个事件处理程序去处理,可以避免为每一个可单击元素分别添加事件处理程序。这种方法需要将事件处理程序放在尽量高的层次,以便接到所有的事件冒泡。
最简单的一种实践是用switch分类处理不同类型的单击。


6.2 删除事件处理程序

还有一种解决办法就是及时将无用的事件处理程序删除,在移除元素或节点之前,最好也手工将绑定在其上的事件处理程序删掉。
最简单的删除方法就是将事件处理程序置为null。

0 0
原创粉丝点击