程序员人生 网站导航

【JavaScript】事件

栏目:htmlcss时间:2016-07-04 16:47:51

所谓事件,就是文档或阅读器窗口中产生的1些特定的交互瞬间

1、事件流

在页面上,单击某个元素的同时,也单击了它的包括容器。事件流就是描写的从页面中接收事件的顺序。IE是事件冒泡流,Netscape是事件捕获流。
事件冒泡:事件开始时,由最具体的元素接收,然后逐级向上传播到较为不具体的节点;(所有现代阅读器都支持事件冒泡)
事件捕获:不太具体的节点最早接收到事件,最具体的节点最后接收到事件。(老版本阅读器不支持)

DOM事件流

DOM2级事件规定的事件流包括3个阶段:1、事件不惑阶段;2、处于目标阶段;3、事件冒泡阶段

这里写图片描述

DOM事件流中,实际的目标在捕获阶段不会接收到时间

2、事件处理程序

事件就是用户或阅读器本身履行的某种动作,如click/load/mousedown,这些都是事件的名字。
事件处理程序:是响应某个事件的函数

为事件指定事件处理函数的方法有3种:

1、HTML事件处理程序

某个元素支持的每种事件,都可以在元素内部,使用与事件处理程序同名的HTML属性来指定。这个属性的值是能够履行的JavaScript代码,既可以包括要履行的具体动作,也能够调用在页面其他地方定义的脚本。

<input type="button" value="点我有欣喜" onclick="alert('hello,vicky!')" />

缺点:
1、存在时差,用户可能会在HTML元素加载完就触发相应事件,而这时候相应的事件处理程序还没有加载完,就会报错
2、使得HTML代码和JavaScript代码耦合,所以不推荐使用!

2、DOM0级事件处理程序

每一个元素都有自己的事件处理程序属性,这些属性通常全部小写,将这类属性的值设置为1个函数,就能够指定事件处理程序。

var btn = document.getElementById("btn");//获得1个要操作对象的援用 btn.onclick = function () { alert("hello vicky!"); }

3、DOM2级事件处理程序

DOM2级事件定义了两个方法:addEventListener( ) removeEventListener( ),都接受3个参数,要处理的事件名,事件处理函数,1个布尔值(true表示在捕获阶段调用事件处理程序,false表示在冒泡阶段)

var btn = document.getElementById("btn"); btn.addEventListener("click", function (){ alert("hello vicky!"); },false); btn.addEventListener("click",function () { alert("hello jay!") }, false);//可以添加多个事件处理程序,且依照其添加的顺序触发

通过addEventListener()添加的事件处理程序只能通过 removeEventListener()来移出。事件处理程序是在其依附的元素的作用域中运行

4、IE事件处理程序

IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。事件处理程序在全局作用域中运行,添加的事件处理程序都会被添加到冒泡阶段

var btn = document.getElementById("btn"); btn.attachEvent("onclick",function(){ alert("hello vicky!"); }); btn.attachEvent("onclick",function () { alert("hello jay!"); });//添加多个事件处理程序,以添加顺序的相反顺序履行

5、跨阅读器的事件处理程序

var EventUtil = { //添加事件处理程序 addHandler: function (element,type,handler) { if (element.addEventListener) { element.addEventListener(type,handler,false);//DOM2级 } else if (element.attachEvent) { element.attachEvent("on" + tye,handler);//IE的方法 } else { element["on" + tyle] = handler;//DOM0级 } }, //取消事件处理程序 removeHandler: function (element,type,handler) { if (element.removeEventListener) { element.removeEventListener(type,handler,false); } else if (element.detachEvent) { element.detachEvent("on" + tye,handler); } else { element["on" + tyle] = null; } } }

3、事件对象

在动身DOM上的某个事件时,会产生要给事件对象event

1、DOM中的事件对象

兼容DOM的阅读器会将1个event对象传入到事件处理程序中。event对象包括于创建它的特定事件有关的属性和方法。

//属性 bubbles:Boolean //表明事件是不是冒泡 cancelable:Boolean //表明是不是可以取消事件的默许行动 currentTarget:Element //事件处理程序当前正在处理事件的那个元素 defaultPrevented:Boolean //是不是调用了preventDefault() detail:Integer //细节信息 eventPhase: Integer //1,捕获阶段;2,处于目标阶段;3,冒泡阶段 target:Element //事件的目标 trusted:Boolean //是不是为阅读器生成 type:Sting //被触发事件的类型 //方法 preventDefault() //取消事件的默许行动 stopImmediatePropagation() //取消事件的进1步捕获或冒泡,同时禁止任何事件处理程序被调用 stopPropagation() //取消事件的进1步捕获或冒泡。

在事件处理程序内部,对象this始终等于currentTarget的值,target则只包括事件的实际目标

2、IE中的事件对象

不同的地方:
1、event对象作为window对象的1个属性存在
2、事件的目标 window.event.srcElement
3、returnValue=false相当于preventDefault()

3、跨阅读器的事件对象

var EventUtil = { //获得事件对象 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.cancleBubble = true; } } }

4、事件类型

1、UI事件

UI事件:指的是那些不1定与用户操作有关的事件。主要有:
load事件:页面完全加载后再window上面触发
unload事件:页面完全卸载后在window上触发
abort事件:用户停止下载进程时,如果嵌入的内容还没加载完在object元素上面触发
error事件:产生毛病时触发
select事件:用户选择文本框时触发
resize事件:窗口或框架的大小变化时触发
scroll事件:用户转动带转动条的元素中的内容时触发

(1)load事件

当页面完全加载后,就会触发window上面的load事件

1)可以为图象设置load事件。

注意:在创建新的img元素时,要在指定其src属性之前先指定事件。新图象元素不1定要从添加到文档后才开始下载,只要设置了src属性就会开始下载。

2)为script元素指定事件处理程序

注意:与图象不同,只有在设置了script元素的src属性并将该元素添加到文档后,才会开始下载JavaScript文件,即指定src属性和指定事件处理程序的前后顺序不重要。

(2)unload事件

在文档被完全卸载后触发,只要用户从1个页面切换到另外一个页面,就会产生unload事件。

(3)resize事件

当阅读器窗口被调剂到1个新的高度或宽度时,就会触发resize事件
注意:不要在这个事件的处理程序中加入计算量大的代码,由于这些代码很有可能会被频繁履行,从而致使阅读器反应明显变慢。固然,这个缺点也是有办法来解决的,那就是函数节流 ,详情请见之前博客【JavaScript】函数节流

2、焦点事件

blur:在元素失去焦点时触发
focus:在元素取得焦点时触发
这两个事件都不冒泡,所有阅读器都支持它们

3、鼠标与滚轮事件

(1)鼠标事件

click:单击主鼠标或按下回车键触发
dbclick:双击主鼠标时触发
mousedown:用户按下了任意鼠标按钮时触发
mouseenter:在鼠标光标从元素外部首次移动到元素范围以内时触发。此事件不冒泡,且光标移动到后代元素上不触发
mouseleave:位于元素上的光标移动到元素范围以外时触发
mouseover:鼠标指针在元素内部移动时触发
mouseout:鼠标指针由1个元素移到另外一个元素上时触发
mouseup:释放鼠标按钮时触发

//鼠标事件触发顺序 (1)mousedown (2)mouseup (3)click (4)mousedown (5)mouseup (6)dbclick

1)位置属性:
这里写图片描述
clientX,clientY:到阅读器视口区的左侧和上边的值
screenX,screenY:到显示屏幕左侧和上边的值
offsetX,offsetY:到元素左侧和上边的值
2)修改键
shiftKey,ctrlKey,altKey,metaKey.

//打印出用户按下的修改键 var text = document.getElementById("text"); EventUtil.addHandler(text,"keydown",function (event) { var event = EventUtil.getEvent(event); var keys = new Array(); if (event.shiftKey) { keys.push("shift") } if (event.ctrlKey) { keys.push("ctrl"); } console.log(keys); }) ;

3)相干元素
产生mouseover和mouseout事件时,还会触及更多的元素。这两个事件都会触及把鼠标指针从1个元素的编辑以内移动到另外一个元素的边界以内

//获得相干元素 getRelatedTarget: function (event) { if (event.relatedTarget) {//DOM return event.relatedTarget; } else if (event.toElement) {//mouseout时IE的toElement保存相干元素 return event.toElement; } else if (event.fromElement) {//mouseover时IE的fromElement保存相干元素 return event.fromElement; } else { return null; } }

4)鼠标按钮
event对象存在1个button属性,其值有3种:0表示主鼠标按钮,1表示中间的鼠标按钮,2表示次鼠标按钮

(2)鼠标滚轮事件

将mousewheel事件处理程序指定给页面中的任何元素或document对象,便可处理鼠标滚轮交互操作
使用鼠标事件应注意的问题:
(1)使用click事件履行代码
(2)不要使用onmouseover向用户显示新的选项。缘由是 屏幕浏览器中,没法触发mousedown和mouseover事件
(3)不要使用dbclick履行重要的操作。由于键盘没法触发这个事件

4、键盘事件

keydown:用户按下键盘上的任意键时触发
keypress:用户按下键盘上的字符键时触发
keyup:用户释放键盘上的键时触发
textInput:在文本插入文本框之前触发

(1)键码

在产生keydown和keyup事件时,event对象的keyCode属性中会包括1个代码,与键盘上1个特定的键对应。
这里写图片描述
这里写图片描述

(2)字符编码

产生keypress事件意味着按下的键会影响到屏幕中文本的显示。
charCode属性:只有在产生keypress事件时才包括值,而且值是ASCII编码。要想跨阅读器获得字符编码,必须首先检测charCode属性是不是可用,如果不可用则使用keyCode

//获得charCode getCharCode: function (event) { if (typeof event.charCode == "number") { return event.charCode; } else { return event.keyCode; } }

(3)textInput事件

用户在可编辑区域中输入字符时,就会触发这个事件
textInput事件的event对象中包括1个data属性,这个属性的值就是用户输入的字符(不是编码)。

var textbox = document.getElementById("textbox"); EventUtil.addHandler(textbox,"textInput",function (event) { event = EventUtil.getEvent(event); alert(event.data); })

5、HTML5事件

(1)contexmenu事件

contextmenu事件表示什么时候应当显示上下文菜单,以便开发人员取消默许的上下文菜单而提供自定义的菜单

//contextmenu事件 EventUtil.addHandler(window,"load",function (event) { var div = document.getElementById("myDiv"); EventUtil.addHandler(div, "contextmenu", function (event) { event = EventUtil.getEvent(event); EventUtil.preventDefault(event); var menu = div.nextElementSibling; menu.style.left = event.clientX + "px"; menu.style.right = event.clientY + "px"; menu.style.visibility = "visible"; }); EventUtil.addHandler(document, "click", function (event) { document.getElementById("myMenu").style.visibility = "hidden"; }) });

这里写图片描述
右键出现自定义的上下文信息

(2)readystatechange事件

readystatechange事件的目的是提供与文档或元素的加载状态有关的信息
可能的状态有5种:

uninitialized(未初始化):对象存在但还没有初始化
loading(正在加载):对象正在加载数据
loaded(加载终了):对象加载数据完成
interactive(交互):可以操作对象了,但还没有完全加载
complete(完成):对象已加载终了

并不是所有对象都会经历readyState的这几个阶段
栗子:

//readystatechange事件,肯定外部js是不是加载终了 EventUtil.addHandler(window, "load", function () { var script = document.createElement("script"); EventUtil.addHandler(script, "readystatechange", function (event) { var event = EventUtil.getEvent(event); var target = event.getTarget(event); if (target.readyState == "loaded" || target.readyState == "complete") { EventUtil.removeHandler(target, "readystatechange", arguments.callee); alert("event.js is loaded"); } }); script.src = "test.js"; document.body.appendChild(script); }); //readystatechange 事件,肯定外部css是不是加载终了 EventUtil.addHandler(window, "load", function () { var link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; EventUtil.addHandler(link,"readystatechange", function (event) { var event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); if (target.readyState == "loaded" || target.readyState == "complete") { EventUtil.removeHandler(target, "readystatechange", arguments.callee); } }); link.href = "test.css"; document.getElementsByTagName("head")[0].appendChild(link); }); //以上两个函数,最重要的是1并检测readyState的两个状态,并在调用了1次事件处理程序后就将其移除

5、事件拜托

1、事件拜托

对”事件处理程序过量“这个问题的解决方案就是事件拜托,事件拜托利用了事件冒泡,只指定1个事件处理程序,就能够管理某1类型的所有事件。比如,click事件会冒泡到document对象上,所以可以为全部页面指定1个onclick事件处理程序,而没必要给每一个可单击的元素分别添加。

事件拜托的优点:
(1)在页面中设置时间处理程序所需的时间更少。只添加1个事件处理程序所需的DOM援用更少,花费时间少
(2)全部页面占用的内存空间更少,能够提升整体性能。

合适使用时间拜托技术的事件有:click/mousedown/mouseup/keydown/keyup/keypress

2、移失事件处理程序

内存中留有那些过时不用的“空事件处理程序”,也是造成Web利用程序内存与性能问题的主要缘由,解决问题的1种方法就是移除这些事件处理程序。

btn.onclick = null;

在页面卸载之前,使用onunload事件,移除所有事件处理程序

6、巩固学习的新知识

String.fromCharCode( ): 可接受1个指定的Unicode值,返回对应的字符串

/\d/.test(String.fromCharCode(EventUtil.getCharCode(event)))//判断按键按下的是不是为数字

hasArrtibute( ):如果存在指定属性,则hasAttribute方法返回true,否则返回false。
specified属性:HTML DOM属性,查明是不是已规定某属性

PS.《JavaScript高级程序设计》书又刷了1遍,还是又学习了很多新的知识,我觉着写博客是1种巩固学习的好方法,看书看1遍,把书上的代码敲1遍,再在博客中梳理1遍,全部知识框架就会很清晰。最近心里也有点着急,看书速度有些慢了,又买了好几本新书,不知道内推之前还来不来的及看完了。英雄不打无准备之仗,所以,加油!

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐