由处理程序来监听某个动作,一旦某个动作发生,那么处理程序就作出响应,这就是观察者模式的简单案例。在JavaScript中,按钮一旦被点击(或者其他动作,拿点击按钮举例),就会有响应的处理程序进行响应,比如,点击按钮弹出一个对话框、鼠标滑过按钮会提示一行字等等,这就是JavaScript中要讲的事件,也属于经典的观察者模式。
- 事件流。
在DOM树中,可能一个<button>元素属于一个<div>元素的子元素,而<div>又属于<html>的子元素。这个时候,点击<button>这个元素,<button>就会触发一个事件(或者一个动作),而<div>、<html>有可能也要接收到这个事件的信号。也就是说,你打了button一下,它的父亲、祖父都会感受到你的打击。这就是事件流。IE的事件流是事件冒泡流。
- 事件冒泡
- IE的事件流叫做事件冒泡。即事件从最深的元素开始接收,然后逐级向上传播。
如:打了孙子一下,孙子感受到疼,然后父亲感知,最后爷爷感知,追本溯源,直到老祖宗感知。
- 事件冒泡的过程图:
- 、
- IE的事件流叫做事件冒泡。即事件从最深的元素开始接收,然后逐级向上传播。
- 事件捕获
- 事件捕获与事件冒泡正好相反,即从最外层开始接收事件,直到最深的元素。
骂了姓张的人,首先张姓的祖宗感到耻辱,接着张姓的爷爷、爸爸、自己分别感受到。
- 事件捕获很少用到。过程图与事件冒泡相反。
- 事件捕获与事件冒泡正好相反,即从最外层开始接收事件,直到最深的元素。
- DOM的事件流
- DOM2级事件包括三个阶段:事件捕获阶段、处理目标阶段、事件冒泡阶段。
先发生事件捕获,传递到最深一层,由具体元素接收到事件,然后冒泡并处理程序。(下面讲到第10节事件对象的target属性时会具体解释这一现象)
- 过程图:
- DOM2级事件包括三个阶段:事件捕获阶段、处理目标阶段、事件冒泡阶段。
- 事件处理程序
- 事件就是用户或者浏览器自身执行的某种动作。而响应某个事件的函数就叫做事件处理程序。
诸如click、load、mouseover都是事件的名字。 事件处理程序的名字则在前面加on,比如:onclick、onload等。
-
示例:
1 <body> 2 <input type="button" value="Click Me" onclick="alert('Clicked')" /> 3 <!--双引号转义--> 4 <input type="button" value="Click Me" onclick="alert("Clicked")" /> 5 6 <script type="text/javascript"> 7 function showMessage(){ 8 alert("Hello world!"); 9 } 10 </script> 11 <input type="button" value="Click Me" onclick="showMessage()" /> 12 <!--防止在函数未加载时点击--> 13 <input type="button" value="Click Me" onclick="try{showMessage();}catch(ex){}" /> 14 </body>
<input>是元素, onclick是事件处理程序的名字,跟value、type一样,是属性。
-
缺点:
- 如果<input>写在<script>上方,函数尚未加载时,用户可能就点击元素,导致报错。所以上面代码13行进行try catch捕获。
- 如果要修改事件函数,那么<input>里的onclick和<script>里的具体函数都要修改,HTML与JavaScript太紧密耦合。
- 事件就是用户或者浏览器自身执行的某种动作。而响应某个事件的函数就叫做事件处理程序。
- DOM0级事件处理程序
- 在JavaScript中,取出要触发的元素,把函数赋值给事件处理程序属性。
1 <body> 2 <input type="button" id="myBtn" value="Click Me" /> 3 <input type="button" id="myRemoveBtn" value="Remove Event Handler" /> 4 <script type="text/javascript"> 5 var btn = document.getElementById("myBtn"); 6 //会在事件流的冒泡阶段处理 7 btn.onclick = function(){ 8 alert(this.id);//this指示当前元素 9 }; 10 11 var removeBtn = document.getElementById("myRemoveBtn"); 12 removeBtn.onclick = function(){ 13 btn.onclick = null;//删除事件处理程序 14 }; 15 </script> 16 </body>
- 在JavaScript中,取出要触发的元素,把函数赋值给事件处理程序属性。
- DOM2级事件处理程序
IE9及其他主流浏览器支持DOM2级事件处理程序。
- DOM2级事件给元素定义了两个方法:
- 指定事件处理程序的操作:addEventListener();
- 删除事件处理程序的操作:removeEventListener();
- DOM2级之于DOM1级最大的优势在于,可以注册多个事件。
比如点击某个按钮,要弹出一个提示框,同时要按钮改变颜色,这时就需要同时添加两个事件处理程序。
- 示例:
<body> <input type="button" id="myBtn" value="Click Me" /> <p>This example won't work in Internet Explorer.</p> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.addEventListener("click", function(){ alert(this.id); }, false); /**第三个参数默认为false,表示在冒泡阶段触发。如果为true,表示在捕获阶段触发,true一般不会用*/ btn.addEventListener("click", function(){ alert("Hello world!"); }, false); </script> </body>
- DOM2级事件给元素定义了两个方法:
- IE事件处理程序
- IE事件给元素定义了两个方法:
- 指定事件处理程序的操作:attachEvent();
- 删除事件处理程序的操作:detachEvent();
- attachEvent()与DOM0级注册事件在作用域上有不同。
- DOM0级:作用域是所属元素。
即:如果在函数中使用this,this指示当前元素
- attachEvent():作用域是全局作用域(即window)。
- DOM0级:作用域是所属元素。
- 添加多个事件处理程序,按相反的顺序触发。
- IE事件给元素定义了两个方法:
- 跨浏览器的事件处理程序
- 为保持兼容,可以写一个公共事件Util。下面是Util中的添加事件示例:
addHandler: function(element, type, handler){ if (element.addEventListener){ element.addEventListener(type, handler, false); } else if (element.attachEvent){ element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }
- 为保持兼容,可以写一个公共事件Util。下面是Util中的添加事件示例:
- 事件对象
- 在触发DOM上的某个事件时,会在方法中传入一个事件对象event(隐藏),这个对象中包含着所有与事件相关的信息。下面列举部分event的属性:
- currentTarget:当前正在处理事件的那个元素。
- target:事件的目标。
在事件处理程序内部,对象this始终等于currentTarget的值,
而target则只包含事件的实际目标。
一般情况下,currentTarget都与target相等。
但是,假如<button>的父元素是<div>,你给<div>元素绑定了一个onclick,
那么这时,<div>元素是currentTarget值,而target是最终目标:<button>(向下捕获)。
由于按钮<button>上并未绑定onclick事件处理程序,
结果click事件就冒泡到了<div>,在那里事件得到处理。
- IE中的事件对象
IE中的事件对象与其他主流浏览器稍微不同,比如,使用DOM0级方法添加事件处理程序时,方法中传入的event对象是window对象的一个属性,event事件对象的目标对象属性为srcElement而非target等等。所以一般情况下会写一个跨浏览器的Util。
- 在触发DOM上的某个事件时,会在方法中传入一个事件对象event(隐藏),这个对象中包含着所有与事件相关的信息。下面列举部分event的属性:
- 事件类型
- 上述举例最多的是onclick事件类型,实际上,事件类型多种多样,如:
- UI事件:用户与界面交互时触发。
- 焦点事件:元素获得或者失去焦点时。
- 鼠标事件:单击、双击、右击等。
- 滚轮事件:鼠标滑轮滚动时。
- 键盘事件:键盘上按下某个键时。
- 等等。
- javascript中最常用的事件就是load,页面全部加载后,就会触发load事件。
- 图像上面也可以触发load事件,当图像加载完毕时可以指定事件。
- 用户从一个页面切换到另一个页面,会触发unload事件。
- 当浏览器窗口大小被调整后,会触发resize事件。
- 键盘事件也经常用到。
- keydown:用户按下键盘上的任意键时触发。按住不放会重复触发。
- keyup:用户释放键盘上的键时触发。
- 在发生keydown或者keyup时,event对象的keyCode属性会包含一个数字,与键盘上的一个特定的键对应。(比如:回车:13;退出:27;左箭头:37;等等)。
- 使用回车键触发事件举例:
<meta http-equiv="content-type" content="text/html; charset=gb2312"/> <script type="text/javascript"> function show () { //火狐不支持window.event,所以加入"或"条件 var e=window.event||arguments.callee.caller.arguments[0]; if(e.keyCode==13){ alert("你按下了回车"); } } </script> <input onkeydown="show();" value="触发键盘试试">
- 上述举例最多的是onclick事件类型,实际上,事件类型多种多样,如:
- 内存和性能
在javascript中,添加到页面上的事件处理程序数量将直接影响到页面整体的运行性能。 每个函数都是对象,都会占用内存。 内存中的对象越多,性能就越差。 所以要利用好事件处理程序,比如使用事件委托等。