由于jquery本身就是web客户端的有力帮手,所以事件对于它来说就显得尤为重要了,事件是脚本编程的灵魂. 所以此内容也是jQuery学习的重点。
在传统的javascript中,注册一个事件也是非常简单的事情,下面我们具体看一下一个简单的示例:
[html] view plaincopyprint?
- document.getElementById("testDiv2").onclick = showMsg;
等效于:
[html] view plaincopyprint?
- <div id="testDiv1" onclick="alert("!!!");">单击事件 1</div>
注意两者的区别了吗? 我们常用的修改元素属性添加事件的方式, 实际上是建立了一个匿名函数:
[html] view plaincopyprint?
- document.getElementById("testDiv1").onclick = function(event)
- {
- alert("!!!");
- };
这个匿名函数的签名和我们手写的showMsg签名相同, 所以可以把showMsg直接赋值给onclick.
这种方式的弊端是:
1. 只能为一个事件绑定一个事件处理函数. 使用"="赋值会把前面为此时间绑定的所有事件处理函数冲掉.
2. 在事件函数(无论是匿名函数还是绑定的函数)中获取事件对象的方式在不同浏览器中要特殊处理:
3. 添加多播委托的函数在不同浏览器中是不一样的.
所以我们首先应该摒弃<div onclick="..."></div>这种通过修改元素属性添加事件的方式. 尽量使用添加多播事件委托的方式为一个事件绑定多个事件处理函数, 比如为document对象的单击事件添加一个关闭弹出层的方法, 使用多播就不会影响document对象原有的事件处理函数.
Jquery事件:
从上面我们看到了javascript中注册事件的弊端了,这些弊端真正避免起来也挺麻烦的,所以jquery想到了这一点,他几乎把javascript中的事件弊端解决到了极点,我们可以很简单的实现我们在javascript中很麻烦才能实现的功能。正所谓有了jQuery, 天天喝茶水. 下面是在jQuery中最常使用的bind()方法举例:
[html] view plaincopyprint?
- $("#testDiv").bind("click", showMsg);
我们为id是testDiv4的元素, 添加列click事件的事件处理函数showMsg.
使用jQuery事件处理函数的好处:
1. 添加的是多播事件委托. 也就是为click事件又添加了一个方法, 不会覆盖对象的click事件原有的事件处理函数.
[javascript] view plaincopyprint?
- $("#testDiv").bind("click", function(event) { alert("one"); });
- $("#testDiv").bind("click", function(event) { alert("two"); });
单击testDiv对象时, 依次提示"one"和"two".
2. 统一了事件名称.
添加多播事件委托时, ie中是事件名称前面有"on". 但是使用bind()函数我们不用区分ie和dom , 因为内部jQuery已经帮我们统一了事件的名称.
3. 可以将对象行为全部用脚本控制.
让HTML代码部分只注意"显示"逻辑. 现在的趋势是将HTML的行为, 内容与样式切分干净. 其中用脚本控制元素行为, 用HTML标签控制元素内容, 用CSS控制元素样式. 使用jQuery事件处理函数可以避免在HTML标签上直接添加事件.
Jquery常用事件函数:
虽然我们可以使用事件处理函数完成对象事件的几乎所有操作, 但是jQuery提供了对常用事件的封装. 比如单击事件对应的两个方法click()和click(fn)分别用来触发单击事件和设置单击事件.
设置单击事件:
[javascript] view plaincopyprint?
- $("#testDiv").click(function(event) { alert("test div clicked ! "); });
$("#testDiv").click(function(event) { alert("test div clicked ! "); });
等效于:
[javascript] view plaincopyprint?
- $("#testDiv").bind("click", function(event) { alert("test div clicked ! "); });
触发单击事件:
[javascript] view plaincopyprint?
- $("#testDiv").click();
等效于
[javascript] view plaincopyprint?
- $("#testDiv").trigger("click");
$("#testDiv").trigger("click");
注意这里等效的是trigger而不是triggerHandler.
下面我们来看一下这些常用的事件函数
方法 |
描述 |
bind() |
向匹配元素附加一个或更多事件处理器 |
blur() |
触发、或将函数绑定到指定元素的 blur 事件 |
change() |
触发、或将函数绑定到指定元素的 change 事件 |
click() |
触发、或将函数绑定到指定元素的 click 事件 |
dblclick() |
触发、或将函数绑定到指定元素的 double click 事件 |
delegate() |
向匹配元素的当前或未来的子元素附加一个或多个事件处理器 |
die() |
移除所有通过 live() 函数添加的事件处理程序。 |
error() |
触发、或将函数绑定到指定元素的 error 事件 |
event.isDefaultPrevented() |
返回 event 对象上是否调用了 event.preventDefault()。 |
event.pageX |
相对于文档左边缘的鼠标位置。 |
event.pageY |
相对于文档上边缘的鼠标位置。 |
event.preventDefault() |
阻止事件的默认动作。 |
event.result |
包含由被指定事件触发的事件处理器返回的最后一个值。 |
event.target |
触发事件的 DOM 元素。 |
event.timeStamp |
该属性返回从 1970 年 1 月 1 日到事件发生时的毫秒数。 |
event.type |
描述事件的类型。 |
event.which |
指示按了哪个键或按钮。 |
focus() |
触发、或将函数绑定到指定元素的 focus 事件 |
keydown() |
触发、或将函数绑定到指定元素的 key down 事件 |
keypress() |
触发、或将函数绑定到指定元素的 key press 事件 |
keyup() |
触发、或将函数绑定到指定元素的 key up 事件 |
live() |
触发、或将函数绑定到指定元素的 load 事件 |
load() |
触发、或将函数绑定到指定元素的 load 事件 |
mousedown() |
触发、或将函数绑定到指定元素的 mouse down 事件 |
mouseenter() |
触发、或将函数绑定到指定元素的 mouse enter 事件 |
mouseleave() |
触发、或将函数绑定到指定元素的 mouse leave 事件 |
mousemove() |
触发、或将函数绑定到指定元素的 mouse move 事件 |
mouseout() |
触发、或将函数绑定到指定元素的 mouse out 事件 |
mouseover() |
触发、或将函数绑定到指定元素的 mouse over 事件 |
mouseup() |
触发、或将函数绑定到指定元素的 mouse up 事件 |
one() |
向匹配元素添加事件处理器。每个元素只能触发一次该处理器。 |
ready() |
文档就绪事件(当 HTML 文档就绪可用时) |
resize() |
触发、或将函数绑定到指定元素的 resize 事件 |
scroll() |
触发、或将函数绑定到指定元素的 scroll 事件 |
select() |
触发、或将函数绑定到指定元素的 select 事件 |
submit() |
触发、或将函数绑定到指定元素的 submit 事件 |
toggle() |
绑定两个或多个事件处理器函数,当发生轮流的 click 事件时执行。 |
trigger() |
所有匹配元素的指定事件 |
triggerHandler() |
第一个被匹配元素的指定事件 |
unbind() |
从匹配元素移除一个被添加的事件处理器 |
undelegate() |
从匹配元素移除一个被添加的事件处理器,现在或将来 |
unload() |
触发、或将函数绑定到指定元素的 unload 事件 |
交互帮助方法:
除了基本的实践, jQuery提供了两个和事件相关的帮助方法: hover( over, out ) 和 toggle( fn, fn2, fn3,fn4,... )
hover函数主要解决在原始javascript中mouseover和mouseout函数存在的问题, 看下面这个示例:
有两个div(红色区域), 里面分别嵌套了一个div(黄色区域). HTML代码如下:
[html] view plaincopyprint?
- <div class="outer" id="outer1">
- Outer 1
- <div class="inner" id="inner1">Inner 1</div>
- </div>
- <div class="outer" id="outer2">
- Outer 2
- <div class="inner" id="inner2">Inner 2</div>
- </div>
- <div id="console"></div>
绑定如下事件:
[javascript] view plaincopyprint?
- <script type="text/javascript">
- function report(event) {
- $('#console').append('<div>'+event.type+'</div>');
- }
- $(function(){
- $('#outer1')
- .bind('mouseover',report)
- .bind('mouseout',report);
- $('#outer2').hover(report,report);
- });
- </script>
Outer1我们使用了mouseover和mouseout事件, 当鼠标从Outer1的红色区域移动到黄色区域时, 会发现虽然都是在outer1的内部移动, 但是却触发了mouseout事件:
很多时候我们不希望出现上图的结果, 而是希望只有鼠标在Outer1内部移动时不触发事件, Outer2使用Hover()函数实现了这个效果:
注意这里的事件名称进入叫做"mouseenter", 离开叫做"mouseleave", 而不再使用"mouseover"和"mouseleave"事件.
有经验的开发人员会立刻想到在制作弹出菜单时, 经常遇到这个问题: 为弹出菜单设置了mouseout事件自动关闭, 但是鼠标在弹出菜单内移动时常常莫名其妙触发mouseout事件让菜单关闭. hover()函数帮助我们很好的解决了这个问题.
2. toggle( fn, fn2, fn3,fn4,... )
toggle函数可以为对象添加click事件绑定函数, 但是设置每次点击后依次的调用函数。
如果点击了一个匹配的元素,则触发指定的第一个函数,当再次点击同一元素时,则触发指定的第二个函数,如果有更多函数,则再次触发,直到最后一个。随后的每次点击都重复对这几个函数的轮番调用。
可以使用unbind("click")来删除。
下面的示例演示如何使用toggle函数:
[html] view plaincopyprint?
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
- <html>
- <head>
- <title>toggle example</title>
- <link rel="stylesheet" type="text/css" href="css/hover.css">
- <script type="text/javascript" src="scripts/jquery-1.3.2-vsdoc2.js"></script>
- <script type="text/javascript">
- $(function()
- {
- $("li").toggle(
- function()
- {
- $(this).css({ "list-style-type": "disc", "color": "blue" });
- },
- function()
- {
- $(this).css({ "list-style-type": "square", "color": "red" });
- },
- function()
- {
- $(this).css({ "list-style-type": "none", "color": "" });
- }
- );
- })
- </script>
- </head>
- <body>
- <ul>
- <li style="cursor:pointer">click me</li>
- </ul>
- </body>
- </html>
结果是每点击一次"click me"变换一次列表符号和文字颜色.
使用jQuery事件对象
使用事件自然少不了事件对象. 因为不同浏览器之间事件对象的获取, 以及事件对象的属性都有差异, 导致我们很难跨浏览器使用事件对象.
jQuery中统一了事件对象, 当绑定事件处理函数时, 会将jQuery格式化后的事件对象作为唯一参数传入:
$("#testDiv").bind("click", function(event) { });
关于event对象的详细说明, 可以参考jQuery官方文档: http://docs.jquery.com/Events/jQuery.Event
jQuery事件对象将不同浏览器的差异进行了合并, 比如可以在所有浏览器中通过 event.target 属性来获取事件的触发者(在IE中使用原生的事件对象, 需要访问event.srcElement).
下面是jQuery事件对象可以在扩浏览器支持的属性:
属性名称 |
描述 |
举例 |
type |
事件类型.如果使用一个事件处理函数来处理多个事件, 可以使用此属性获得事件类型,比如click. |
$("a").click(function(event) { alert(event.type); }); |
target |
获取事件触发者DOM对象 |
$("a[href=http://google.com]").click(function(event) { alert(event.target.href); }); |
data |
事件调用时传入额外参数. |
$("a").each(function(i) { $(this).bind('click', {index:i}, function(e){ alert('my index is ' + e.data.index); }); }); |
relatedTarget |
对于鼠标事件, 标示触发事件时离开或者进入的DOM元素 |
$("a").mouseout(function(event) { alert(event.relatedTarget); }); |
currentTarget |
冒泡前的当前触发事件的DOM对象, 等同于this. |
$("p").click(function(event) { alert( event.currentTarget.nodeName ); }); 结果:P |
pageX/Y |
鼠标事件中, 事件相对于页面原点的水平/垂直坐标. |
$("a").click(function(event) { alert("Current mouse position: " + event.pageX + ", " + event.pageY ); }); |
result |
上一个事件处理函数返回的值 |
$("p").click(function(event) { return "hey" }); $("p").click(function(event) { alert( event.result ); }); 结果:"hey" |
timeStamp |
事件发生时的时间戳. |
var last; $("p").click(function(event) { if( last ) alert( "time since last event " + event.timeStamp - last ); last = event.timeStamp; }); |
上面是jQuery官方文档中提供的event对象的属性. 在"jQuery实战"一书中还提供了下面的多浏览器支持的属性, 时间关系我没有尝试每一个属性, 大家可以帮忙验证是否在所有浏览器下可用:
属性名称 |
描述 |
举例 |
altKey |
Alt键是否被按下. 按下返回true |
|
ctrlKey |
ctrl键是否被按下, 按下返回true |
|
metaKey |
Meta键是否被按下, 按下返回true. meta键就是PC机器的Ctrl键,或者Mac机器上面的Command键 |
|
shiftKey |
Shift键是否被按下, 按下返回true |
|
keyCode |
对于keyup和keydown事件返回被按下的键. 不区分大小写, a和A都返回65. 对于keypress事件请使用which属性, 因为which属性跨浏览时依然可靠. |
|
which |
对于键盘事件, 返回触发事件的键的数字编码. 对于鼠标事件, 返回鼠标按键号(1左,2中,3右). |
|
screenX/Y |
对于鼠标事件, 获取事件相对于屏幕原点的水平/垂直坐标 |
事件对象除了拥有属性, 还拥有事件. 有一些是一定会用到的事件比如取消冒泡 stopPropagation() 等.下面是jQuery事件对象的函数列表:
名称 |
说明 |
举例 |
preventDefault() |
取消可能引起任何语意操作的事件. 比如<a>元素的href链接加载, 表单提交以及click引起复选框的状态切换. |
$("a").click(function(event){ event.preventDefault(); // do something }); |
isDefaultPrevented() |
是否调用过 preventDefault() 方法 |
$("a").click(function(event){ alert( event.isDefaultPrevented() ); event.preventDefault(); alert( event.isDefaultPrevented() ); }); |
stopPropagation() |
取消事件冒泡 |
$("p").click(function(event){ event.stopPropagation(); // do something }); |
isPropagationStopped() |
是否调用过 stopPropagation() 方法 |
$("p").click(function(event){ alert( event.isPropagationStopped() ); event.stopPropagation(); alert( event.isPropagationStopped() ); }); |
stopImmediatePropagation() |
取消执行其他的事件处理函数并取消事件冒泡. 如果同一个事件绑定了多个事件处理函数, 在其中一个事件处理函数中调用此方法后将不会继续调用其他的事件处理函数. |
$("p").click(function(event){ event.stopImmediatePropagation(); }); $("p").click(function(event){ // This function won't be executed }); |
isImmediatePropagationStopped() |
是否调用过 stopImmediatePropagation() 方法 |
$("p").click(function(event){ alert( event.isImmediatePropagationStopped() ); event.stopImmediatePropagation(); alert( event.isImmediatePropagationStopped() ); }); |
这些函数中 stopPropagation() 是我们最长用的也是一定会用到的函数. 相当于操作原始event对象的event.cancelBubble=true来取消冒泡.