从零开始学习jQuery (五) 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>.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

我们最常使用为元素添加onclick元素属性的方式添加事件.

为testDiv2的添加onclick事件的方式是修改Dom属性.

在上一章中已经说明了什么是元素属性, 什么是Dom属性.这两种方式的效果相同. 当单击div时会显示提示框.

请注意, 虽然效果相同, 但是并不等效.

document.getElementById("testDiv2").onclick = showMsg;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

等效于:

<div id="testDiv1" onclick="alert("!!!");">单击事件 1</div>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

注意两者的区别了吗?  我们常用的修改元素属性添加事件的方式, 实际上是建立了一个匿名函数:

document.getElementById("testDiv1").onclick = function(event)
{
alert("!!!");
};

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

这个匿名函数的签名和我们手写的showMsg签名相同, 所以可以把showMsg直接赋值给onclick.

这种方式的弊端是:

1. 只能为一个事件绑定一个事件处理函数.  使用"="赋值会把前面为此时间绑定的所有事件处理函数冲掉.

2. 在事件函数(无论是匿名函数还是绑定的函数)中获取事件对象的方式在不同浏览器中要特殊处理:

IE中,事件对象是window对象的一个属性.事件处理函数必须这样访问事件对象:

 obj.onclick=function()
{
var oEvent = window.event;
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

在DOM标准中,事件对象必须作为唯一参数传给事件处理函数:

 obj.onclick=function()
{
var oEvent = arguments[0];
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

除了使用argument[0]访问此参数, 我们也可以指定参数名称,上面的代码等同于:

 obj.onclick=function(oEvent)
{
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

目前兼容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);
}
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

所以我们首先应该摒弃<div onclick="..."></div>这种通过修改元素属性添加事件的方式. 尽量使用添加多播事件委托的方式为一个事件绑定多个事件处理函数, 比如为document对象的单击事件添加一个关闭弹出层的方法, 使用多播就不会影响document对象原有的事件处理函数.

四. jQuery中的事件


有了jQuery,  我们有了处理对象事件的一系列函数.  上面基础知识还是要懂, 但是再也不用自己去实现处理多播事件委托的函数了.  正所谓有了jQuery, 天天喝茶水. 下面是在jQuery中最常使用的bind()方法举例:

$("#testDiv4").bind("click", showMsg);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

我们为id是testDiv4的元素, 添加列click事件的事件处理函数showMsg.

使用jQuery事件处理函数的好处:

1. 添加的是多播事件委托.  也就是为click事件又添加了一个方法, 不会覆盖对象的click事件原有的事件处理函数.

 $("#testDiv4").bind("click", function(event) { alert("one"); });
$("#testDiv4").bind("click", function(event) { alert("two"); });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

单击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)

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

注意event参数的使用. jQuery中统一了事件对象, 将事件对象作为事件处理函数的唯一参数传递.

data参数我们也要通过event.data 进行访问.  为何要提供data参数呢?

因为我们经常碰到这样的问题: 希望在事件处理中根据事件源的某些数据进行特殊处理.

目前网上有两种存在争议的解决方法:

(1) 使用自定义元素属性存储数据.

比如:

<div id="testDiv5" customer="customer data 1">获取自定义数据-1</div>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }


在事件处理函数中获取数据:

$("#testDiv5").bind("click", function(event) { alert($(event.target).attr("customer")); });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

attr函数是上一讲中的知识, 用于获取元素的"元素属性", 而且可以获取自定义的元素属性. 单击div后将显示:

(2) 使用脚本将数据传递给事件处理函数:

<div id="testDiv6">获取自定义数据-2</div>

元素没有任何的自定义属性, 添加事件处理函数时将额外的数据传递:

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

$("#testDiv6").bind("click", { customer: "customer data 2" }, function(event) { alert(event.data.customer) });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

点击div后的结果和方法1相同:

方法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>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }


当单击".trigger"按钮时, 会调用两次Focesed, 并且input元素获得了焦点:

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

也就是说, trigger函数出发了浏览器默认的获取焦点的行为,让input元素获得了焦点, 所以再次调用了focus事件处理函数.

triggerHandler只调用为focus事件绑定的事件处理函数, 而不引发浏览器行为, 所以最后input元素没有获得焦点.

六.快捷事件 Event Helpers


BUG提示:jquery-1.3.2-vsdoc2.js 这个最新的官方带智能提示的类库, 无法使用快捷事件, 比如click(), focus(). 使用其他版本的类库则没有问题.

虽然我们可以使用事件处理函数完成对象事件的几乎所有操作, 但是jQuery提供了对常用事件的封装. 比如单击事件对应的两个方法click()和click(fn)分别用来触发单击事件和设置单击事件.

设置单击事件:

$("#testDiv").click(function(event) { alert("test div clicked ! "); });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

等效于:

$("#testDiv").bind("click", function(event) { alert("test div clicked ! "); });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

触发单击事件:

$("#testDiv").click();

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

等效于

$("#testDiv").trigger("click");

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

注意这里等效的是trigger而不是triggerHandler.

此类方法在jQuery中英文叫做Event Helpers, 我找不到很好的翻译方式, 所以按照功能称其为"快捷方法",  征集好的翻译名称!

下面是jQuery的快捷方法列表:

由于都是都是对应的事件, 所以不再写说明和举例了.










































































































































名称 说明 举例
blur( )    
blur( fn )    
change( )    
change( fn )    
click( )    
click( fn )    
dblclick( )    
dblclick( fn )    
error( )    
error( fn )    
focus( )    
focus( fn )    
keydown( )    
keydown( fn )    
keypress( )    
keypress( fn )    
keyup( )    
keyup( fn )    
load( fn )    
mousedown( fn )    
mouseenter( fn )    
mouseleave( fn )    
mousemove( fn )    
mouseout( fn )    
mouseover( fn )    
mouseup( fn )    
resize( fn )    
scroll( fn )    
select( )    
select( fn )    
submit( )    
submit( fn )    
unload( fn )    

七. 交互帮助方法


除了基本的实践, jQuery提供了两个和事件相关的帮助方法: hover( over, out )toggle( fn, fn2, fn3,fn4,... )

1. hover( over, out )

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>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

绑定如下事件:

 <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>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

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函数:

<!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>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

结果是每点击一次"click me"变换一次列表符号和文字颜色.

八.使用jQuery事件对象


使用事件自然少不了事件对象.  因为不同浏览器之间事件对象的获取, 以及事件对象的属性都有差异, 导致我们很难跨浏览器使用事件对象.

jQuery中统一了事件对象,  当绑定事件处理函数时,  会将jQuery格式化后的事件对象作为唯一参数传入:

$("#testDiv").bind("click", function(event) { });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

关于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的插件开发.
作者:张子秋
出处:http://www.cnblogs.com/zhangziqiu/

(0)

相关推荐

  • jQuery事件对象的属性和方法详解

    jQuery事件对象的属性和方法,供大家参考,具体内容如下 事件对象的属于与方法有很多,但是我们经常用的只有那么几个,这里我主要说下作用与区别 event.type:获取事件的类型 触发元素的事件类型 $("a").click(function(event) { alert(event.type); // "click"事件 }); event.pageX 和 event.pageY:获取鼠标当前相对于页面的坐标 通过这2个属性,可以确定元素在当前页面的坐标值,鼠标

  • jquery 事件对象属性小结

    使用事件自然少不了事件对象.  因为不同浏览器之间事件对象的获取, 以及事件对象的属性都有差异, 导致我们很难跨浏览器使用事件对象. jQuery中统一了事件对象,  当绑定事件处理函数时,  会将jQuery格式化后的事件对象作为唯一参数传入: $("#testDiv").bind("click", function(event) { }); 关于event对象的详细说明, 可以参考jQuery官方文档: http://docs.jquery.com/Events

  • jQuery事件对象总结

    本人对jquery的event不懂,搜索了很多关于jquery event事件介绍,下面我来记录一下,有需要了解jquery event事件用法的朋友可参考.希望此文章对各位有所帮助. 学习要点: 事件对象 冒泡和阻止默认行为 一.事件对象 在JS中,我们已经详细讨论了JS的事件对象,这里就挑几个常用的探讨 <code class=" hljs xml"></code><div><code class=" hljs xml"

  • jQuery中事件对象e的事件冒泡用法示例介绍

    之前查手册的时候没有看到有事件对象这一概念,当时我想实现的是点击一个文本框出现一个下拉多选框,在文本框失去焦点是触发blur事件,从而使下拉框隐藏起来.但是当我要选择多选框是也会使它隐藏,就不能进行选择了,这让我很郁闷.查了一天的资料,终于在脱离了焦点这一块.在网上发现有一个事件冒泡的东西,发现通过点击可以实现我的这一功能. e.stopPropagation()阻止事件冒泡 复制代码 代码如下: <head> <title></title> <script sr

  • 读jQuery之八 包装事件对象

    比如,停止事件冒泡IE用 cancelBubble ,标准浏览器则用 stopPropagation . 获取事件源对象,IE用 srcElement ,标准浏览器则用 target 诸如此类. jQuery 对原生事件对象的修复和包装主要使用 jQuery.Event 类和 jQuery.event.fix 方法. 复制代码 代码如下: jQuery.Event = function( src ) { // Allow instantiation without the 'new' keywo

  • JavaScript事件学习小结(五)js中事件类型之鼠标事件

    相关阅读: JavaScript事件学习小结(五)js中事件类型之鼠标事件 http://www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 http://www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员(属性和方法) http://www.jb51.net/article/86262.htm JavaScript事件学习小结(二)js事件处理程序 http://www

  • 从零开始学习jQuery (五) jquery事件与事件对象

    一.摘要 事件是脚本编程的灵魂. 所以本章内容也是jQuery学习的重点. 本文将对jQuery中的事件处理以及事件对象进行详细的讲解. 二.前言 本篇文章是至今为止本系列内容最多的一篇, 足以可见其重要性.  大家反映要多列举示例. 我会在时间允许的情况下尽量多列举示例. 真正的投入生产使用的实例暂时还无法加入到文章中, 但是可能最后我会列举一些作品供大家借鉴. 另外本人水平有限, 因为我不是UI设计师. 文章可能有错误的地方, 希望大家帮忙指出, 一起学习一起进步. 在技术的世界里我们是没有

  • JavaScript事件学习小结(三)js事件对象

    相关阅读: JavaScript事件学习小结(五)js中事件类型之鼠标事件 http://www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 http://www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员(属性和方法) http://www.jb51.net/article/86262.htm JavaScript事件学习小结(二)js事件处理程序 http://www

  • jQuery学习总结之jQuery事件

    首先,我们来看一个有用的实例,来加深以前所掌握的知识,其中有些是在前边出现过的. 复制代码 代码如下: <img id="imgGoogle" src="http://www.google.com.hk/intl/zh-CN/images/logo_cn.png" alt="google.com" /> <input type="button" id="btnHide" value=&qu

  • jQuery学习笔记之jQuery的事件

    一.事件绑定 1.事件绑定函数 事件的绑定函数为如下形式: .bind(type [,data],fn) type:类型 如click..... data:参数 fn:事件执行的函数 例子 复制代码 代码如下: $(function(){ $(#id1).click(function(){ $(#id2).show();//id2显示 }) ; }); 二.合成事件 1.鼠标滑过事件 .hover(enter,leave) enter:鼠标光标移动到对象时触发的函数 leave:鼠标光标移出对象

  • 从零开始学习jQuery (一) 开天辟地入门篇

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章是入门第一篇, 主要是简单介绍jQuery, 通过简单示例指导大家如何编写jQuery代码以及搭建开发环境. 详细讲解了如何在Visual Studio中配合使用jQuery. 转载请注明子秋出品!博客园首发! 二.前言 首先道个歉! "从零开始学习ASP.NET MVC"系列文章在即将介绍Filter时就没有更新了, 原因就是

  • 从零开始学习jQuery (四) jQuery中操作元素的属性与样式

    一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得大家学习. 二.前言 通过前面几章我们已经能够完全控制jQuery包装集了, 无论是通过选择器选取对象, 或者从包装集中删除,过滤元素. 本章将讲解如何使用jQuery获取和修改元素属性和样式. 三. 区分DOM属性和元素属性 一个img标签: <img src="images/image.1.jpg" id="hibiscus" alt="

  • 从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本文是介绍两个最常用的jQuery插件. 分别用于表单验证和自动完成提示(类似google suggest). 二.前言 研究别人的作品真是一件花时间而且痛苦的过程. 当然也和本人英文不好有关. 总觉得控件作者写了很多文档但是都不够系统, 需要深入研究很多的实例后才能了解作者的思路.所以学习和研究一个插件需要很高成本, 如果发现了Bug并修复需要

  • 从零开始学习jQuery (十) jQueryUI常用功能实战

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本文是实战篇. 使用jQueryUI完成制作网站的大部分常用功能. 二.前言 经过公司内部收集, 整理了一些经常使用javascript实现的功能.  实现这些功能的主角不是让人眼花缭乱的jQuery插件,  而是jQuery UI. 如果你还在为了一个小小的特效而去下载并安装插件, 发现Bug还没有人替你解决. 记住插件是我们没有办法的最后选择

  • 从零开始学习jQuery (二) 万能的选择器

    一.摘要 本章讲解jQuery最重要的选择器部分的知识. 有了jQuery的选择器我们几乎可以获取页面上任意的一个或一组对象, 可以明显减轻开发人员的工作量. 二.前言 编写任何javascript程序我们要首先获得对象, jQuery选择器能彻底改变我们平时获取对象的方式, 可以获取几乎任何语意的对象, 比如"拥有title属性并且值中包含test的<a>元素", 完成这些工作只需要编写一个jQuery选择器字符串. 学习jQuery选择器是学习jQuery最重要的一步.

随机推荐