从零开始学习jQuery (一) 开天辟地入门篇javascript
从零开始学习jQuery (三) 管理jQuery包装集html
从零开始学习jQuery (四) 使用jQuery操做元素的属性与样式java
从零开始学习jQuery (六) jQuery中的Ajaxjquery
从零开始学习jQuery (七) jQuery动画-让页面动起来!程序员
从零开始学习jQuery (八) 插播:jQuery实施方案编程
从零开始学习jQuery (九) jQuery工具函数浏览器
从零开始学习jQuery (十) jQueryUI经常使用功能实战app
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
事件是脚本编程的灵魂. 因此本章内容也是jQuery学习的重点. 本文将对jQuery中的事件处理以及事件对象进行详细的讲解.
本篇文章是至今为止本系列内容最多的一篇, 足以可见其重要性. 你们反映要多列举示例. 我会在时间容许的状况下尽可能多列举示例. 真正的投入生产使用的实例暂时还没法加入到文章中, 可是可能最后我会列举一些做品供你们借鉴. 另外本人水平有限, 由于我不是UI设计师. 文章可能有错误的地方, 但愿你们帮忙指出, 一块儿学习一块儿进步. 在技术的世界里咱们是没有任何利益瓜葛. 但愿你们都抱着彼此鼓励的心态, 对于回复中的激进评论我也都会考虑, 可是但愿可以彼此尊重, 保护博客园这片程序员的净土!
曾经在个人 "Javascript公共脚本库系列(二): 添加事件多播委托的方法" 和 "Javascript公共脚本库系列(三): 格式化事件对象/事件对象详解" 两篇文章中, 曾讲解过javascript中的事件和事件对象.
首先看一下咱们常用的添加事件的方式:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>javascript中的事件</title> <script type="text/javascript" src="scripts/jquery-1.3.2-vsdoc2.js"></script> <script type="text/javascript"> $(function() { document.getElementById("testDiv2").onclick = showMsg; }) function showMsg(event) { alert("!!!"); } </script> </head> <body> <div id="testDiv1" onclick="showMsg();">单击事件 1</div> <div id="testDiv2">单击事件 2</div> </body> </html>
咱们最常使用为元素添加onclick元素属性的方式添加事件.
为testDiv2的添加onclick事件的方式是修改Dom属性.
在上一章中已经说明了什么是元素属性, 什么是Dom属性.这两种方式的效果相同. 当单击div时会显示提示框.
请注意, 虽然效果相同, 可是并不等效.
document.getElementById("testDiv2").onclick = showMsg;
等效于:
<div id="testDiv1" onclick="alert("!!!");">单击事件 1</div>
注意二者的区别了吗? 咱们经常使用的修改元素属性添加事件的方式, 其实是创建了一个匿名函数:
document.getElementById("testDiv1").onclick = function(event) { alert("!!!"); };
这个匿名函数的签名和咱们手写的showMsg签名相同, 因此能够把showMsg直接赋值给onclick.
这种方式的弊端是:
1. 只能为一个事件绑定一个事件处理函数. 使用"="赋值会把前面为此时间绑定的全部事件处理函数冲掉.
2. 在事件函数(不管是匿名函数仍是绑定的函数)中获取事件对象的方式在不一样浏览器中要特殊处理:
IE中,事件对象是window对象的一个属性.事件处理函数必须这样访问事件对象:
obj.onclick=function() { var oEvent = window.event; }
在DOM标准中,事件对象必须做为惟一参数传给事件处理函数:
obj.onclick=function() { var oEvent = arguments[0]; }
除了使用argument[0]访问此参数, 咱们也能够指定参数名称,上面的代码等同于:
obj.onclick=function(oEvent)
{
}
目前兼容DOM的浏览器有Firefox,Safari,Opera,IE7等.
3. 添加多播委托的函数在不一样浏览器中是不同的.
下面是在"Javascript公共脚本库系列(二): 添加事件多播委托的方法"文章中, 提供的兼容多浏览器添加多播委托的方法:
//统一的为对象添加多播事件委托的方法 /* 参数说明: oTarget : 要添加事件的对象.好比"document". sEventType : 事件类型.好比单击事件"click". fnHandler : 发生事件时调用的方法. 好比一个静态函数"hideCalendar" 使用举例: //单击页面的任何元素,只要没有取消冒泡,均可以关闭日历控件 var cf = document.getElementById("CalFrame"); if( cf != null && hideCalendar != null ) { ScriptHelper.addEventListener( document, "click", hideCalendar ); } */ scriptHelper.prototype.addEventListener = function(oTarget, sEventType, fnHandler) { if( oTarget.addEventListener )//for dom { oTarget.addEventListener( sEventType, fnHandler, false ) } else if( oTarget.attachEvent )//for ie { oTarget.attachEvent( "on" + sEventType, fnHandler); } }
因此咱们首先应该摒弃<div onclick="..."></div>这种经过修改元素属性添加事件的方式. 尽可能使用添加多播事件委托的方式为一个事件绑定多个事件处理函数, 好比为document对象的单击事件添加一个关闭弹出层的方法, 使用多播就不会影响document对象原有的事件处理函数.
有了jQuery, 咱们有了处理对象事件的一系列函数. 上面基础知识仍是要懂, 可是不再用本身去实现处理多播事件委托的函数了. 正所谓有了jQuery, 每天喝茶水. 下面是在jQuery中最常使用的bind()方法举例:
$("#testDiv4").bind("click", showMsg);
咱们为id是testDiv4的元素, 添加列click事件的事件处理函数showMsg.
使用jQuery事件处理函数的好处:
1. 添加的是多播事件委托. 也就是为click事件又添加了一个方法, 不会覆盖对象的click事件原有的事件处理函数.
$("#testDiv4").bind("click", function(event) { alert("one"); }); $("#testDiv4").bind("click", function(event) { alert("two"); });
单击testDiv4对象时, 依次提示"one"和"two".
2. 统一了事件名称.
添加多播事件委托时, ie中是事件名称前面有"on". 可是使用bind()函数咱们不用区分ie和dom , 由于内部jQuery已经帮咱们统一了事件的名称.
3. 能够将对象行为所有用脚本控制.
让HTML代码部分只注意"显示"逻辑. 如今的趋势是将HTML的行为, 内容与样式切分干净. 其中用脚本控制元素行为, 用HTML标签控制元素内容, 用CSS控制元素样式. 使用jQuery事件处理函数能够避免在HTML标签上直接添加事件.
下面是基础的jQuery事件处理函数:
事件处理 Event Handling:
名称 | 说明 | 举例 |
为每个匹配元素的特定事件(像click)绑定一个事件处理器函数。 | 当每一个段落被点击的时候,弹出其文本: $("p").bind("click", function(){ |
|
one( type, [data], fn ) | 为每个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。 | 当全部段落被第一次点击的时候,显示全部其文本: $("p").one("click", function(){ |
trigger( event, [data] ) | 在每个匹配的元素上触发某类事件。 这个函数也会致使浏览器同名的默认行为的执行。好比,若是用trigger()触发一个'submit',则一样会致使浏览器提交表单。若是要阻止这种默认行为,应返回false。 你也能够触发由bind()注册的自定义事件 |
给一个事件传递参数: $("p").click( function (event, a, b) { |
triggerHandler( event, [data] ) | 这个特别的方法将会触发指定的事件类型上全部绑定的处理函数。但不会执行浏览器默认动做. | 若是你对一个focus事件执行了 .triggerHandler() ,浏览器默认动做将不会被触发,只会触发你绑定的动做: $("#old").click(function(){ |
unbind( type, fn ) | bind()的反向操做,从每个匹配的元素中删除绑定的事件。 若是没有参数,则删除全部绑定的事件。 你能够将你用bind()注册的自定义事件取消绑定。 若是提供了事件类型做为参数,则只删除该类型的绑定事件。 若是把在绑定时传递的处理函数做为第二个参数,则只有这个特定的事件处理函数会被删除。 |
把全部段落的全部事件取消绑定: $("p").unbind() 将段落的click事件取消绑定: $("p").unbind( "click" ) 删除特定函数的绑定,将函数做为第二个参数传入: var foo = function () { |
bind()是最常使用的函数, 注意方法签名上data参数, 能够在事件处理以前传递一些附加的数据:
function handler(event) { alert(event.data.foo); } $("p").bind("click", {foo: "bar"}, handler)
注意event参数的使用. jQuery中统一了事件对象, 将事件对象做为事件处理函数的惟一参数传递.
data参数咱们也要经过event.data 进行访问. 为什么要提供data参数呢?
由于咱们常常碰到这样的问题: 但愿在事件处理中根据事件源的某些数据进行特殊处理.
目前网上有两种存在争议的解决方法:
(1) 使用自定义元素属性存储数据.
好比:
<div id="testDiv5" customer="customer data 1">获取自定义数据-1</div>
在事件处理函数中获取数据:
$("#testDiv5").bind("click", function(event) { alert($(event.target).attr("customer")); });
attr函数是上一讲中的知识, 用于获取元素的"元素属性", 并且能够获取自定义的元素属性. 单击div后将显示:
(2) 使用脚本将数据传递给事件处理函数:
<div id="testDiv6">获取自定义数据-2</div>
元素没有任何的自定义属性, 添加事件处理函数时将额外的数据传递:
$("#testDiv6").bind("click", { customer: "customer data 2" }, function(event) { alert(event.data.customer) });
点击div后的结果和方法1相同:
方法1便于存储和查找数据. 可是自定义属性经过不W3C验证.
方法2必需要本身想办法存储数据, 而且要制定规则查找指定元素的数据.
从"开发人员"的角度方法1要更加简单直观. 可是缺点比较严重. 因此如何取舍请你们本身决定.
one( type, [data], fn ) 函数和bind同样, 可是只执行一次.
虽然为元素绑定了某些事件, 好比click, 可是有时但愿在程序中触发这些事件, 这两个函数能够实现此功能.
主要区别是trigger会出发浏览器默认的动做, 而triggerHandler不会出发.
经过下面的实例能够明确的区分这两个函数:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>jQuery事件处理:trigger和triggerHandler示例</title> <script type="text/javascript" src="scripts/jquery-1.3.2-vsdoc2.js"></script> <script type="text/javascript"> $(function() { $("#old").click(function() { $("#divResult").html(""); $("input").trigger("focus"); }); $("#new").click(function() { $("#divResult").html(""); $("input").triggerHandler("focus"); }); $("input").focus(function() { $("<span>Focused!</span>").appendTo("#divResult"); }); }) </script> </head> <body> <button id="old"> .trigger("focus")</button> <button id="new"> .triggerHandler("focus")</button><br /> <br /> <input type="text" value="To Be Focused" /> <div id="divResult"></div> </body> </html>
当单击".trigger"按钮时, 会调用两次Focesed, 而且input元素得到了焦点:
单击".triggerHandler"按钮时, 只调用一次,而且input元素没有得到焦点:
也就是说, trigger函数出发了浏览器默认的获取焦点的行为,让input元素得到了焦点, 因此再次调用了focus事件处理函数.
triggerHandler只调用为focus事件绑定的事件处理函数, 而不引起浏览器行为, 因此最后input元素没有得到焦点.
BUG提示:jquery-1.3.2-vsdoc2.js 这个最新的官方带智能提示的类库, 没法使用快捷事件, 好比click(), focus(). 使用其余版本的类库则没有问题.
虽然咱们可使用事件处理函数完成对象事件的几乎全部操做, 可是jQuery提供了对经常使用事件的封装. 好比单击事件对应的两个方法click()和click(fn)分别用来触发单击事件和设置单击事件.
设置单击事件:
$("#testDiv").click(function(event) { alert("test div clicked ! "); });
等效于:
$("#testDiv").bind("click", function(event) { alert("test div clicked ! "); });
触发单击事件:
$("#testDiv").click();
等效于
$("#testDiv").trigger("click");
注意这里等效的是trigger而不是triggerHandler.
此类方法在jQuery中英文叫作Event Helpers, 我找不到很好的翻译方式, 因此按照功能称其为"快捷方法", 征集好的翻译名称!
下面是jQuery的快捷方法列表:
因为都是都是对应的事件, 因此再也不写说明和举例了.
除了基本的实践, jQuery提供了两个和事件相关的帮助方法: hover( over, out ) 和 toggle( fn, fn2, fn3,fn4,... )
hover函数主要解决在原始javascript中mouseover和mouseout函数存在的问题, 看下面这个示例:
有两个div(红色区域), 里面分别嵌套了一个div(黄色区域). HTML代码以下:
<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>
绑定以下事件:
<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()函数帮助咱们很好的解决了这个问题.
toggle函数能够为对象添加click事件绑定函数, 可是设置每次点击后依次的调用函数。
若是点击了一个匹配的元素,则触发指定的第一个函数,当再次点击同一元素时,则触发指定的第二个函数,若是有更多函数,则再次触发,直到最后一个。随后的每次点击都重复对这几个函数的轮番调用。
可使用unbind("click")来删除。
下面的示例演示如何使用toggle函数:
<!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格式化后的事件对象做为惟一参数传入:
$("#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来取消冒泡.
事件是javascript的灵魂, 我花了好久写这篇文章,翻译jQuery官方的API文档. 列表中的不少例子直接从官网上摘抄的, 有些列表中的方法我也没有用过, 因此若是你们发现问题请及时通知我修改.
接下来的文章将分别讲解Ajax和动画效果. 最后经过讲解两个我修改的jQuery插件来学习jQuery的插件开发.