jQuery代码优化:基本事件篇

标签: 前端开发 JavaScript jQuery 事件 性能优化 | 发表时间:2011-12-22 13:19 | 作者:直觉
出处:http://www.kekaku.com

jQuery对事件系统的抽象与优化也是它的一大特色。本文仅从事件系统入手,简要分析一下jQuery为什么提供mouseenter和mouseleave事件,它们与标准的mouseover、mouseout事件有什么区别。

事件模型

说到事件,就要追溯到网景与微软的“浏览器大战”了。当时,事件模型还没有标准,两家公司的实现就是事实标准。网景在Navigator中实现了“事件捕获”的事件系统,而微软则在IE中实现了一个基本上相反的事件系统,叫做“事件冒泡”。这两种系统的区别在于当事件发生时,相关元素处理(响应)事件的优先权不同。

下面举例说明这两种事件机制的区别。假设文档中有如下结构:

<div>
    <span>
        <a>...</a>
    </span>
</div>

因为这三个元素是嵌套的,所以单击了a,实际上也就单击了span和div。换句话说,这三个元素都应该有处理单击事件的机会。在事件捕获机制下,处理这个单击事件的优先次序是:div > span > a;而在事件冒泡机制下,处理这个单击事件的优先次序则是:a > span > div。

后来,W3C的规范要求浏览器同时支持捕获和冒泡机制,并允许开发人员选择把事件注册到哪个阶段。于是就有了下面这个注册事件的标准方法:

target.addEventListener(type, listener, useCapture Optional );

其中:

  • type:字符串,表示监听的事件类型
  • listener:监听器对象(JavaScript函数),在指定事件发生时可以收到通知
  • useCapture:布尔值,是否注册到捕获阶段

在实际应用开发中,为了确保与IE(因为它不支持捕获)兼容,useCapture一般都指定为false(默认值也是false)。换句话说,只把事件注册到冒泡阶段;对于上面那个简单的例子来说,响应顺序就是:a > span > div。

冒泡的副作用

如前所述,IE的冒泡事件模型基本上成为了事实标准。但冒泡有一个副作用。

仍以前面的文档结构为例,假设它是界面中的一个菜单项,我们希望用户鼠标离开div时隐藏菜单。于是,我们给div注册了一个mouseout事件。如果用户鼠标是从div离开的,那么一切正确。而如果用户鼠标是从a或span离开的,问题就来了。因为由于事件冒泡,从这两个元素开始分派的mouseout事件都会传播到div,从而导致鼠标并没有离开div,菜单就提前隐藏了。

当然,冒泡的副作用不难避免。比如,给div内部的每个元素都注册mouseout事件,并使用.stopPropagation()方法阻止事件进一步传播。对于IE,就得将事件对象的cancelBubble属性设置为true,取消事件冒泡。不过,这仍然回到自己处理浏览器不兼容性问题的老路上了。

优化方案

为了避免冒泡的副作用, jQuery提供了mouseenter和mouseleave事件,就使用它们来代替mouseover和mouseout吧

下面这个摘自jQuery的内部函数withinElement,就是为mouseenter和mouseleave提供支持的。翻译了一下注释,仅供大家参考。

// 下面这个函数用于检测事件是否发生在另一个元素的内部
// 在 jQuery.event.special.mouseenter 和 mouseleave 处理程序中使用
var withinElement = function( event ) {
    // 检测 mouse(over|out) 是否还在相同的父元素内
    var parent = event.relatedTarget;
 
    // 设置正确的事件类型
    event.type = event.data;
 
    // Firefox 有时候会把 relatedTarget 指定一个 XUL 元素
    // 对于这种元素,无法访问其 parentNode 属性
    try {
 
        // Chrome 也类似,虽然可以访问 parentNode 属性
        // 但结果却是 null
        if ( parent && parent !== document && !parent.parentNode ) {
            return;
        }
 
        // 沿 DOM 树向上
        while ( parent && parent !== this ) {
            parent = parent.parentNode;
        }
 
        if ( parent !== this ) {
            // 如果实际正好位于一个非子元素上面,那好,就处理事件
            jQuery.event.handle.apply( this, arguments );
        }
 
    // 假定已经离开了元素,因为很可能鼠标放在了一个XUL元素上
    } catch(e) { }
}

结论

在jQuery里,可以使用mouseenter和mouseleave事件来避免事件冒泡的副作用。

(注:本文基于《jQuery基础教程(第3版)》相关章节内容编撰而成。)

您可能也喜欢:

jQuery代码优化:选择符篇

13个实用的jQuery插件

jQuery代码优化:遍历篇

10个最新的轻量jQuery Slider插件

使用jQuery和YQL,以Ajax方式加载外部内容
无觅

相关 [jquery 代码 优化] 推荐:

jQuery代码优化:基本事件篇

- - 可咔酷 | 网络杂货铺
jQuery对事件系统的抽象与优化也是它的一大特色. 本文仅从事件系统入手,简要分析一下jQuery为什么提供mouseenter和mouseleave事件,它们与标准的mouseover、mouseout事件有什么区别. 说到事件,就要追溯到网景与微软的“浏览器大战”了. 当时,事件模型还没有标准,两家公司的实现就是事实标准.

Jquery性能优化

- - JavaScript - Web前端 - ITeye博客
一、注意定义jQuery变量的时候添加var关键字. 这个不仅仅是jQuery,所有javascript开发过程中,都需要注意,请一定不要定义成如下:. $loading = $('#loading'); //这个是全局定义,不知道哪里位置倒霉引用了相同的变量名,就会郁闷至死的. 二、请使用一个var来定义变量.

Java代码优化

- - ImportNew
2016年3月修改,结合自己的工作和平时学习的体验重新谈一下为什么要进行代码优化. 在修改之前,我的说法是这样的:. 就像鲸鱼吃虾米一样,也许吃一个两个虾米对于鲸鱼来说作用不大,但是吃的虾米多了,鲸鱼自然饱了. 代码优化一样,也许一个两个的优化,对于提升代码的运行效率意义不大,但是只要处处都能注意代码优化,总体来说对于提升代码的运行效率就很有用了.

50个必备的实用jQuery代码段

- Zhaojing - HTML5研究小组
本文会给你们展示50个jquery代码片段,这些代码能够给你的javascript项目提供帮助. 其中的一些代码段是从jQuery1.4.2才开始支持的做法,另一些则是真正有用的函数或方法,他们能够帮助你又快又好地把事情完成. 如果你发现你任何可以做得更好的地方的话,欢迎把你的版本粘贴在评论中!. 如何修改jQuery默认编码(例如默认UTF-8改成改GB2312):.

可以直接拿来用的15个jQuery代码片段

- - CSDN博客Web前端推荐文章
jQuery里提供了许多创建交互式网站的方法,在开发Web项目时,开发人员应该好好利用jQuery代码,它们不仅能给网站带来各种动画、特效,还会提高网站的用户体验. 本文收集了15段非常实用的jQuery代码片段,你可以直接复制黏贴到代码里,但请开发者注意了,要理解代码再使用哦. 下面就让我们一起来享受jQuery代码的魅力之处吧.

10个超棒jQuery表单操作代码片段

- - 前端观察
jQuery绝对是一个伟大的开源javascript类库,是帮助我们快速和高效开发前端应用的利器. 可能大家在日常的开发过程中常常会处理表单相关的javascript,在今天这篇代码片段分享文章中,这里收集了10个超棒超实用的jQuery表单处理代码,希望能够在大家的开发过程中帮助大家更好更快的处理表单相关问题,希望大家喜欢.

jQuery参考实例 1.2 在DOM加载完毕,页面元素完全加载之前运行jQuery/JavaScript代码

- - CSDN博客推荐文章
本文翻译自jQuery Cookbook (O’Reilly 2009) 1.2 Executing jQuery/JavaScript Code After the DOM Has Loaded but Before Complete Page Load. 主流的JavaScript应用程序一般只在DOM完全加载后才运行JS代码.

jQ.Mobi——针对移动设备优化的jQuery

- - HTML5研究小组
appMobi已经开放了 jQ.Mobi的源代码,它对jQuery进行了重写,与 jQuery Mobile竞争以分享开发者份额. jQ.Mobi是jQuery的部分重写版本,但针对HTML5和移动设备做了优化. 它的文件大小只有3KB,而jQuery则有35KB,并且据 JSPerf test的数据,它在Android上要比jQuery快3倍,在iOS上快2.2倍.

代码优化概要

- raphael - 酷壳 - CoolShell.cn
Dobb’s Blogger的Walter Bright写的《Overlooked Essentials For Optimizing Code. 我编写程序至今有35年了,我做了很多关于程序执行速度方面优化的工(一个示例),我也看过其它人做的优化. 我发现有两个最基本的优化技术总是被人所忽略. 注意,这两个技术并不是避免时机不成熟的优化.