原文出处:http://blog.csdn.net/guoquanyou/archive/2008/10/17/3091906.aspx
jQuery 内的 Events 模块是向 Web 应用程序添加交互性的第一步,因为事件通常是页面上发生的事情的触发器。正如我在简介中提到的,您不应该认为事件只发生在 Form 元素 — 实际上,任何元素都能触发事件,因此应该充分利用这一点来更轻松地构建定制的小部件,以及添加一些独特却又不局限于特定 Form 元素的交互。
众所周知,大多数事件都 基于 Form 元素。演示这些方法最好的方式就是使用它们。在开始深入研究可用的函数之前,一定要注意:Events 模块针对每个函数都遵循一种模式。每个事件函数都包含两种形式:一个没有任何参数,一个包含一个函数作为参数。二者间的差异十分重要,而且这对各个函数都是一致的。没有参数的函数将实际激发该事件。换而言之,调用 click()
将实际导致该按钮被单击。在实际单击该按钮,或其 click()
函数被调用时,将会调用 click(function)
。是不是很困惑?这只是文字上的描述,举例说明之后,您就会清楚了。
// ID="myButton"点击会激发该事件.例如可以使用在表单的提交等. $("#myButton").click(); // ID="myButton"被点击时,会切换ID=myDiv标签的状态,如果元素是可见的,切换为隐藏的;如果元素是隐藏的,切换为可见的。 $("#myButton").click(function(){ $("#myDiv").toggle(); }).click(); |
如下所列的事件都符合我在之前所介绍的设计模式,而且也都具有与其相关联的两个函数。为了简单起见,我只列举了第一个:
blur()
- 在 Form 元素失去焦点时调用,例如,用 tab 键移出具有焦点的文本字段change()
- 在 Form 元素失去焦点,并且其值因获得焦点而更改时调用。Internet Explorer 和 Firefox 对此的处理稍微不同。click()
- 当在页面元素(不一定是 Form 元素)上单击时调用dblclick()
- 当在页面元素(不一定是 Form 元素)上双击时调用error()
- 当元素出现内部错误时调用,不同的浏览器对此的处理不同,可能很多人都亲自体验过focus()
- 当某个 Form 元素获得焦点时调用keydown()
- 当页面元素在其上/内发生一个 keypress 时调用keyup()
- 当页面元素在其上/内释放一个 keypress 时调用keypress()
- 当相同的页面元素相继发生 keydown 和 keypress 时调用select()
- 文本在文本字段内被选中时调用,而不是内容在组合框内被选中时(这时发生的是更改事件)调用。submit()
- 提交 Form 时调用
还有一些函数不遵守上文概括的模式,而且也只包含一个可调用的函数。我将这些例外也列于此,但它们不常用:
resize(fn)
- 对象调整大小时调用scroll(fn)
- iframe 卷起时调用load(fn)/unload(fn)
- 对象在页面上加载/重载时发生
此外,您可以想像得到,一些事件是与鼠标紧密相连的。由于这些事件常被误用,所以我将它们包括在第三节。认识到这一点后,jQuery 已经用特定的函数替代了其中的一些事件。我将它们列于此,只是为了直接与底层的 DOM 事件相匹配,但对于所有的实际使用,最好使用其他的方法。比如,当鼠标在某个元素上按下或释放时,就会调用 mousedown(fn)
和 mouseup(fn)
方法。然而,更多时候,却应该调用 click()
方法,因为此方法也会作为事件抛出,而且它更符合预期的行为,更不容易出错。试想一下这样的情况:用户在某个按钮上按下鼠标,发现错了,立即松开鼠标而不是释放鼠标。如果用户用所定义的 mouseup(fn)
在另一个页面元素之上释放鼠标,那么应该发生什么行为呢?理想情况下,这两个函数的使用应该限于对界面的拖放,因为这种情况下单击不会有合适的替代。
Event 模块的最后两个方法 mouseover(fn)
和 mouseout(fn)
目前在很多 Web 站点上都很常见。它们常被用来显示悬浮帮助、图片显示所需的相框和基于鼠标指针所在位置而发生的颜色改变。JQuery 认识到这两个函数还将很常用,但很多人都不能正确使用它们,这就导致很多错误。人们并不是有意要将 bug 引入其代码,而是自己不会编写嵌套组件或应对其他复杂情况的代码。因此,jQuery 向 Event 模块添加了一个新方法来替代这两个函数,这个方法就是 hover(fn1, fn2)
函数。
|
页面交互性的一个体现就是它从页面的某个区域获得信息并将信息传送到其他位置的能力。这可以很具体,比如从一个文本字段获得信息后将信息放入一个表内;也可以很宽泛,比如从一个组合框获得信息后将信息传给服务器,然后将服务器的响应再放入另外一个不同的组合框内。交互性的核心就是页面信息的传递。
在页面上保存信息有很多不同的方式,在页面的某个元素内存储信息的方法就更多样了。您可能会想,一个简单的 <p> 所包含的信息肯定没有一个文本字段那么多(这不一定正确),因而,访问信息也有很多不同的函数。同样地,您自己可能已经有了这样的结论:如果能从页面元素获得信息,那么也应该可以在这些元素上放置信息。实际上,每个页面元素都是一个数据对象,其中包含由 getter/setter 方法封装的变量。JavaBean 模型和 jQuery 的实际差异是方法名称和某些元素不适合特定函数的限制。
在深入研究这些方法之前,让我们先来看看什么信息能 存储到页面元素内。简单一些的,像 a <p>,可能只包含 CLASS 或 ID 信息。而像 <img> 则可能包含更多信息,比如 “src”、“alt”、“width” 和 “height”。而复杂一些的,像 < input type="password"> 则可能包含 “defaultValue”、“maxLength”、“readOnly” 或 “accessKey” 等信息。
这种潜在变量的多样性促使 jQuery 创建了一种广义函数来访问它们。这个函数是 attr(name)
,可用来访问来自任何页面元素的信息。我们将通过几个示例来了解其工作原理。
<img src="/images/space.gif" id="spacer" class="a b c" alt="blank"> // 调用attr()方法,返回对应属性值 $("#spacer").attr("src"); // 返回值为"/images/space.gif" $("#spacer").attr("alt"); // 返回值为 "blank" // 对img进行循环 $(img).each(function(){ $(this).attr("id"); // 返回其ID,为"spacer" }); |
在试图向页面添加交互性时,此函数十分有用。实际上,在添加 data()
函数(如下所示)之前,通常都必须将所需信息压缩到一个可用变量内。例如,假设有一个页面具有两个框架,第一个框架显示选项卡,底部框架显示每个选项卡的内容,那么可以这样设置:
<td> <div class="tab" id="/messages.jsp">Messages</div> </td> // 点击class="tab"标签,会在把 “指定的框架”的location设置成该id的值。 |
除了获得 每个元素上的属性值外,还可以设置 这些值。其效果与以编程方式更改元素外观或行为相同。
// 修改图片的src属性为myimage.jpg $("img").attr("src", "myimage.jpg"); // 修改超级链接的href属性为mypage.html $("a").attr("href", "mypage.html"); // 修改password的maxLength属性为10 $(":password").attr("maxLength", "10"); |
页面上的 Form 元素具有一个特殊的函数,该函数可以针对这些元素调用以获得附加到元素的值。在处理表单和验证时,这一点尤其便利,而且在用 Form 元素创建交互 Web 站点时更有可能会用到这些函数。
// 检查文本内容是否为空,不为空则获取,为空则提示 $(":textfield").each(function(){ if ($(this).val() == "") $(this).next().text("Error"); }); // 确认密码和新输入密码是否相等,不相等,则提示 |
还有其他一些函数,可用来获得包含在某些标记之内的信息。那么这有什么用途呢?比如说,您可以获得包含在某个 <td> 标记内的所有信息并进行替换,或者您也可以将所有 <p> 内的文本变成小写的。获得这些信息的方式有两种,但不能为此使用 attr()
函数。与所有其他的属性函数类似,这些函数也有相应的 setter 方法。第一个是 html()
函数,它能返回某个标记的所有 innerHTML。另一个是 text()
,它能返回某个标记内的所有文本。那么二者有何区别呢?html()
函数能返回包括 HTML 标记在内的文本,而 text()
则会分离二者,只返回内含的文本。以下示例展示了它们的不同之处。
// 对每个单元格进行判断,如果为空,则赋予“-”作为占位符 |
此外,最近还向 jQuery 库添加了用于属性的 data()
函数。它源自 jQuery UI 项目并且已纳入 jQuery 的整体项目之中。起初,UI 项目开发人员只是觉得他们不想破坏某些页面元素的可用属性,于是就想到要找到一种方法,用来根据自己的需要创建能存储信息的属性。回顾上文提到过的选项卡的例子。我其实 “破坏” 了此 DIV 的 ID 内的链接,而这显然不是最理想的方法。但是,受 jQuery 以前版本的限制,这在当时是惟一的选择。有了 data()
函数之后,这个问题就有了更好的解决方案。不妨将 data()
函数视为用来访问包含在每个页面元素的内部 Map 的一种方式。一个 Map 实际上就是键-值对的集合。这就让开发人员可以创建他们想要给页面元素提供的任何定制属性,并能给该属性附加任意值。最终的结果就是代码的编写更简单,而且当项目规模不断增大时,代码的维护也更容易。接下来,让我们用新的 data()
函数重写上文提到的示例:
<td> <div class="tab"></div> </td> // 在Jquery中为期初始化. $(".tab").eq(0).text("Messages"); $(".tab").eq(0).data("link", "messages.jsp"); $(".tab").click(function(){ window.parent.frames['content'].location = $(this).data("link"); }); // 在JSP中,和jQuery混合使用. <% String[] tabNames; String[] links; for (int i=0; i<tabNames.length; i++) { %> $(".tab").eq(<%=i%>).text("<%=tabNames[i]%>"); $(".tab").eq(<%=i%>).data("link", "<%=links[i] %>"); <% } %> $(".tab").click(function(){ window.parent.frames['content'].location = $(this).data("link"); }); |
本文最后的这个部分将要介绍如何在不调整样式表或重载此页面的情况下动态地处理页面的 CSS。我们将能够通过简单更改颜色、字体等向页面添加一些基本效果。jQuery 的 CSS 实际上是整个库最初的创意来源。其目标是让页面上的 CSS 编程更容易。正如您所见,此项目随后得到了充分的发展。但是项目的初衷并没有改变,jQuery 的确简化了 CSS 编程。不过,我还是先要说明一点,即 jQuery 为处理 CSS 所提供的那些传统函数实际上已经不能适应当今的 Web 环境。然后,我会介绍可以使用的其他函数(也是 jQuery 内的)。
有两个基本函数可用来处理页面上的 CSS。可以先以字符串传递单个属性,然后再以字符串传递单个值,也可以用字符串/字符串数组的形式一次传递。这两个函数的功能基本相同,并且可以很容易地更改页面的 CSS。
// 为div的css赋值--方式(一) $("div").css("backgroundColor", "#ff0000"); // 为div的css赋值--方式(二) $("div").css("backgroundColor", "red"); // 为div的css赋值--方式(三) $("div").css({backgroundColor: "#ff0000"}); // notice the braces and lack of quotes |
可以看出这些函数非常简单直观,很容易理解和掌握。不过,考虑到目前 Web 页面设计的潮流,这些函数还存在一些问题。常规的 Web 页面都是从页面删除样式,然后在样式表中填入一个外部文件或代码片段。如果能采用其他办法,您肯定不 希望将样式代码放入 JavaScript 代码中。否则,将来更改站点的外观将十分困难。
幸运的是,现在已经有了替代函数,它既能提供所需的代码分离,又能让 CSS 处理简单直观。这些函数允许从页面元素添加和删除类。通过将这些类的样式放入外部样式表,就能分离样式、数据和事件,这种分离对于复杂的页面至关重要。请看以下这些示例:
清单 10. 更佳的 CSS 处理 - addClass() 和 removeClass()
// 判断文本是否为空,是否有样式? $(":textfield").each(function(){ if ($(this).val() == "")//如果为空 { $(this).next().text("Error"); // 为其添加红色样式 $(this).addClass("input_error"); } // 不为空,但是样式已经具有 else if ($(this).hasClass("input_error")) { $(this).next().text(""); // 去除内容,删掉样式 |
如这个示例所示,通过引用在外部样式表内定义的类来调整 CSS 是一种更可取的处理 CSS 的方法。它让 Web 站点创建者通过更改样式表就能改变整个站点 错误消息的处理方式,而不再像采用 css()
方法时那样,必须追究代码的每个实例。虽然这些方法直观易用,但是不太适合大型 Web 应用程序,应该避免采用 addClass()
和 removeClass()
方法。
要综合使用以上知识,让我们再来看看这个示例应用程序。它是一个具有交互性的 Web 应用程序,试图创建一个 RIA 并给用户这样的感觉:他们处理电子邮件所用的这个 Web 应用程序非常类似于桌面应用程序。在本例中,将利用 Event、Attribute 和 CSS 模块来定义 Web 邮件应用程序将如何处理鼠标单击和双击。以下所示的屏幕截图显示了真实的效果。当用户在表的一个行上单击时,此行将会改变颜色以突出显示用户的当前选择。当用户在消息上双击时,用户就能看到消息,但如果用户读的是条新消息,此行的背景颜色会改变以表明此消息不再是未读消息。
图 1. 在某行上单击
图 2. 在某行上双击
清单 11. 综合学到的知识
// 在JSP文件中,通过for循环来显示对应的行信息. <% for (int i=0; i<messages.size(); i++) { MessageData message = messages.get(i); %> <tr class="messageRow" id="<%=message.id %>"> // 点击时,先移除原来的样式(可能刚才已经点过,而被设置的样式),再为被点击对象添加新的样式. $(".messageRow").click(function() { $(".messageRow").removeClass("message_selected"); $(this).addClass("message_selected"); }); // 双击时,先移除当前对象的样式。再显示详细信息 |
随着应用程序不断从桌面向浏览器转移,像 jQuery 这样的 JavaScript 库的将越来越重要。应用程序会越来越复杂,这就使跨浏览器的 jQuery 成为所有 Web 应用项目的必要工具。由于易于使用和功能完备,jQuery 逐渐从其他 JavaScript 库中脱颖而出,成为很多开发人员的最佳选择。
通过这个 jQuery 系列的第二篇文章,您实际体会到了 Web 页面上的交互、了解如何在客户端实现基本交互(无需从服务器获得信息),并借此扩展了自己的 jQuery 知识。您先是接触了 Event 模块,该模块定义页面元素如何响应各种交互,其中包括鼠标交互、键盘交互和焦点交互。事件是 Web 页面上的交互的最主要的驱动器,而且它们不必附加于 Form 元素。我随后讨论了属性以及如何恰当地从页面元素获得属性,如何在页面元素上设置属性。您看到了通用的 attr()
函数可用于每个元素,并且 Form 元素有获得其值的特殊函数。您还看到了新添加到 jQuery 的 data()
函数,此函数可充当每个页面元素的 HashMap,让程序员可以创建所需的任何属性。最后,您了解到如何修改页面元素的 CSS,而不需重新加载页面。您还体验了 css()
函数的简单和直观。但是为了分离页面的样式和 jQuery 代码,您和您的团队最好选择用 addClass()
和 removeClass()
函数替代前面那些函数。
本文的最后的一部分将您所学到的这三个模块综合起来,展示了示例邮件应用程序如何处理鼠标交互。通过突出显示单击的行以及在适当的时候对消息进行 “未读” 标记,可以区分鼠标单击和双击,然后为特定于消息的数据向服务器发送一个 Ajax 调用,将消息编号传递给服务器。
在本系列的下一篇文章中,我们将要深入研究 jQuery 内的 Ajax 函数,了解它如何消除处理 Ajax 所涉及到的大量复杂特性,而使其简单到像通常那样只需调用 JavaScript 函数。此外,我们还会谈到 jQuery 内的 Effects 模块,对于为用户创建额外的交互和视觉效果,这十分有用。下一篇文章中的最后部分将会总结整个演示邮件应用程序和我们的 jQuery 课程。到那时,希望您能自信地将这个库添加到自己的 Web 应用程序中。