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" _disibledevent=>
<div id="testDiv2">单击事件 2</div>
</body>
</html>
我们最常使用为元素添加onclick元素属性的方式添加事件.
为testDiv2的添加onclick事件的方式是修改Dom属性.
在上一章中已经说明了什么是元素属性, 什么是Dom属性.这两种方式的效果相同. 当单击div时会显示提示框.
请注意, 虽然效果相同, 但是并不等效.
document.getElementById("testDiv2").onclick = showMsg;
等效于:
<div id="testDiv1" _disibledevent=>
注意两者的区别了吗? 我们常用的修改元素属性添加事件的方式, 实际上是建立了一个匿名函数:
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 _disibledevent=>对象的单击事件添加一个关闭弹出层的方法, 使用多播就不会影响document对象原有的事件处理函数.
四. jQuery中的事件有了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:
名称说明举例bind( type, [data], fn )
为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数。当每个段落被点击的时候,弹出其文本:
$("p").bind("click", function(){
alert( $(this).text() );
});
one( type, [data], fn )为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。当所有段落被第一次点击的时候,显示所有其文本:
$("p").one("click", function(){
alert( $(this).text() );
});
trigger( event, [data] )在每一个匹配的元素上触发某类事件。
这个函数也会导致浏览器同名的默认行为的执行。比如,如果用trigger()触发一个'submit',则同样会导致浏览器提交表单。如果要阻止这种默认行为,应返回false。
你也可以触发由bind()注册的自定义事件
给一个事件传递参数:
$("p").click( function (event, a, b) {
// 一个普通的点击事件时,a和b是undefined类型
// 如果用下面的语句触发,那么a指向"foo",而b指向"bar"
} ).trigger("click", ["foo", "bar"]);
triggerHandler( event, [data] )这个特别的方法将会触发指定的事件类型上所有绑定的处理函数。但不会执行浏览器默认动作.如果你对一个focus事件执行了 .triggerHandler() ,浏览器默认动作将不会被触发,只会触发你绑定的动作:
$("#old").click(function(){
$("input").trigger("focus");
});
$("#new").click(function(){
$("input").triggerHandler("focus");
});
$("input").focus(function(){ $("<span>Focused!</span>").appendTo("body").fadeOut(1000); });
unbind( type, fn )bind()的反向操作,从每一个匹配的元素中删除绑定的事件。
如果没有参数,则删除所有绑定的事件。
你可以将你用bind()注册的自定义事件取消绑定。
如果提供了事件类型作为参数,则只删除该类型的绑定事件。
如果把在绑定时传递的处理函数作为第二个参数,则只有这个特定的事件处理函数会被删除。
把所有段落的所有事件取消绑定:
$("p").unbind()
将段落的click事件取消绑定:
$("p").unbind( "click" )
删除特定函数的绑定,将函数作为第二个参数传入:
var foo = function () {
// 处理某个事件的代码
};
$("p").bind("click", foo); // ... 当点击段落的时候会触发 foo
$("p").unbind("click", foo); // ... 再也不会被触发 foo
五.常用事件函数举例1.bind( type, [data], fn ) 函数举例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后将显示:

jQuery框架学习第五天:事件与事件对象

(2) 使用脚本将数据传递给事件处理函数:
<div id="testDiv6">获取自定义数据-2</div>
元素没有任何的自定义属性, 添加事件处理函数时将额外的数据传递:
$("#testDiv6").bind("click", { customer: "customer data 2" }, function(event) { alert(event.data.customer) });
点击div后的结果和方法1相同:

jQuery框架学习第五天:事件与事件对象

方法1便于存储和查找数据. 但是自定义属性通过不W3C验证.
方法2必须要自己想办法存储数据, 并且要制定规则查找指定元素的数据.
从"开发人员"的角度方法1要更加简单直观. 但是缺点比较严重. 所以如何取舍请大家自己决定.
one( type, [data], fn ) 函数和bind一样, 但是只执行一次.
2. trigger( event, [data] )triggerHandler( event, [data] )虽然为元素绑定了某些事件, 比如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元素获得了焦点:

jQuery框架学习第五天:事件与事件对象

单击".triggerHandler"按钮时, 只调用一次,并且input元素没有获得焦点:

jQuery框架学习第五天:事件与事件对象

也就是说, trigger函数出发了浏览器默认的获取焦点的行为,让input元素获得了焦点, 所以再次调用了focus事件处理函数.
triggerHandler只调用为focus事件绑定的事件处理函数, 而不引发浏览器行为, 所以最后input元素没有获得焦点.
Tags: 

延伸阅读

最新评论

发表评论