千古前端图文教程:jQuery 事件机制与进阶知识详解——从事件绑定、坐标操作到链式编程与插件扩展

原创2026-09-30 12:38:391,669 阅读
文章标签:前端教程文档知识库

千古前端图文教程:jQuery 事件机制与进阶知识详解——从事件绑定、坐标操作到链式编程与插件扩展

本篇是「千古前端图文教程」jQuery 系列(47-jQuery的介绍和选择器.md → 48-jQuery动画详解.md → 49-jQuery操作DOM.md → 本篇)的进阶收尾篇,聚焦 jQuery 的事件机制、坐标与尺寸操作、链式编程与隐式迭代、多库共存与插件机制五大主题。读完本篇,你将掌握 on()/off() 统一事件绑定与解绑、event 事件对象的完整用法(含键盘按键实战)、offset()/position()/scrollTop() 等坐标 API 的区别,并理解 end()、each()、$.noConflict() 以及 jquery.color.js、jquery.lazyload.js 等插件的工作原理,能够独立完成五角星评分、按键变色等经典交互案例。

jQuery 设置宽度和高度

jQuery 提供了专门操作元素尺寸的方法,与 css() 方法互为补充。

高度操作 height()

$(selector).height();     // 不带参数表示获取高度
$(selector).height(200);  // 带参数表示设置高度

宽度操作 width()

$(selector).width();     // 不带参数表示获取宽度
$(selector).width(200);  // 带参数表示设置宽度

经典问题:css() 获取高度 与 height() 获取高度 的区别

这是面试和日常开发中非常经典的一个辨析题:

$("div").css("height");     // 返回的是 string 类型,例如:"30px"
$("div").height();          // 返回的是 number 类型,例如:30

区别总结如下:

方法 返回类型 示例返回值 适用场景
$("div").css("height") string "30px" 需要拼接单位或直接用于样式
$("div").height() number 30 常用于数学计算(如累加、比较、参与动画运算)

$("div").height() 返回的是 number 类型,直接参与数学运算而无需 parseInt() 转换,因此做尺寸计算(比如自适应布局、动画位移计算)时优先使用它。这与 49-jQuery操作DOM.md 中 css(属性) 获取样式的规则一致:获取样式时若匹配多个元素,返回的是 jQuery 对象中第一个元素的值。

jQuery 的坐标操作

坐标操作是 jQuery 中用于定位元素、处理滚动距离的四大核心方法:offset()、position()、scrollTop()、scrollLeft()。

offset() 方法:相对 document 文档的位置

$(selector).offset();
$(selector).offset({left: 100, top: 150});

作用:获取或设置元素相对于 document 文档的位置。参数解释:

  • 无参数:表示获取。返回值为 {left: num, top: num},是相对于 document(整个页面文档)的位置。
  • 有参数:表示设置。参数建议使用 number 数值类型,传入形如 {left: 100, top: 150} 的对象。

注意:设置 offset 后,如果元素本身没有定位(默认值 static),则会被修改为 relative。也就是说 offset() 的设置操作会自动帮元素加上定位上下文,这一点与 position() 有明显区别。

position() 方法:相对最近的有定位父元素的位置

$(selector).position();

作用:获取相对于其最近的带有定位的父元素的位置。返回值为对象:{left: num, top: num}。

注意:position() 只能获取,不能设置。在下方完整示例代码中可以看到,$(".box2").position().top = "100px" 这种写法是无效的——修改返回对象的属性并不会改变元素的实际位置。

scrollTop() 方法:被卷去的头部距离

$(window).scrollTop();
$(selector).scrollTop(100);

作用:获取或者设置元素被卷去的头部的距离(即滚动条向下滚动的距离)。参数解释:

  • 无参数:表示获取偏移。
  • 有参数:表示设置偏移,参数为数值类型。

scrollLeft() 方法:水平方向滚动的位置

$(window).scrollLeft();
$(selector).scrollLeft(100);

作用:获取或者设置元素水平方向滚动的位置。参数解释:

  • 无参数:表示获取偏移。
  • 有参数:表示设置偏移,参数为数值类型。

完整代码示范:offset / position / scrollTop 对比

原文档给出的完整示例,非常直观地对比了四者的差异:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        body {
            height: 5000px;
        }

        .box1 {
            width: 300px;
            height: 300px;
            position: relative;
            margin: 10px;
            overflow: auto;
            background-color: pink;
        }

        .box2 {
            width: 200px;
            height: 400px;
            position: absolute;
            top: 50px;
            left: 50px;
            background-color: yellow;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        $(function () {
            //距离页面最顶端或者最左侧的距离和有没有定位没有关系
            $("button").eq(0).click(function () {
                alert($(".box2").offset().top);
            })

            //距离页面最顶端或者最左侧的距离和有没有定位没有关系
            $("button").eq(1).click(function () {
                $(".box2").offset({"left": 1000, "top": 1000});
            })

            //距离父系盒子中带有定位的盒子的距离(获取的就是定位值,和margin/padding无关)
            $("button").eq(2).click(function () {
                alert($(".box2").position().top);
            })

            //距离父系盒子中带有定位的盒子的距离(获取的就是定位值,和margin/padding无关)
            //注意:position()只能获取,不能设置,此行代码无效
            $("button").eq(3).click(function () {
                $(".box2").position().top = "100px";
            })

            //获取被卷去的头部
            $("button").eq(4).click(function () {
                alert($(window).scrollTop());
            })

            //设置被卷去的头部
            $("button").eq(5).click(function () {
                $(window).scrollTop(100);
            })
        })
    </script>
</head>
<body>
<div class="box1">
    <div class="box2"></div>
</div>
<button>offset().top获取</button>
<button>offset().top设置</button>
<button>position().top获取</button>
<button>position().top设置</button>
<button>scrollTop()</button>
<button>scrollTop()</button>
</body>
</html>

代码要点解读:

  • offset().top 与元素是否定位无关,始终返回元素相对整个 document 顶端的距离;
  • position().top 返回的是元素相对父级中最近的有定位盒子(.box1,position: relative)的距离,即定位值本身,与 margin/padding 无关;
  • $(window).scrollTop() 常用于「回到顶部」「滚动加载更多」等场景,而 $(selector).scrollTop(100) 则是编程式控制滚动位置。

jQuery 的事件机制

常见的事件绑定(简写形式)

jQuery 为常用事件提供了简洁的绑定写法,handler 为事件处理函数:

  • click(handler) —— 单击事件
  • blur(handler) —— 失去焦点事件
  • mouseenter(handler) —— 鼠标进入事件
  • mouseleave(handler) —— 鼠标离开事件
  • dblclick(handler) —— 双击事件(注意原文档中的拼写为 dbclick,标准事件名为 dblclick)
  • change(handler) —— 改变事件,如文本框值改变、下拉列表值改变等
  • focus(handler) —— 获得焦点事件
  • keydown(handler) —— 键盘按下事件

这些简写形式本质上都是对底层绑定方法的封装,日常写起来非常快捷;但若需要事件委托(把事件绑定到未来动态创建的元素上)或同时绑定多个事件,则应使用下面介绍的 on() 方式。

on 方式绑定事件(jQuery 1.7+ 统一方案)

最早 jQuery 采用的是 bind、delegate 等方式绑定事件。jQuery 1.7 版本之后,用 on() 统一了所有的事件处理方法,此方法兼容 zepto(移动端类似于 jQuery 的一个轻量级库,详见 51-Zepto入门.md 中 Zepto 与 jQuery「语法、API 大部分都一样」的说明)。

格式举例:

$(document).on("click mouseenter", ".box", {"name": 111}, function (event) {
    console.log(event.data);      // event.data 获取的就是第三个参数这个 json
    console.log(event.data.name); // event.data.name 获取的是 name 的值
});

参数解释:

  • 第一个参数 events:绑定事件的名称,可以是由空格分隔的多个事件(标准事件或者自定义事件)。上方代码绑定的是单击事件 click 和鼠标进入事件 mouseenter。
  • 第二个参数 selector:执行事件的后代元素(实现了事件委托:事件绑定在 document 上,但只有匹配该选择器的后代元素触发时才执行 handler)。
  • 第三个参数 data:传递给事件处理函数的数据,事件触发的时候通过 event.data 来使用(也就是说,可以通过 event 拿到 data)。
  • 第四个参数 handler:事件处理函数。

简单点的写法(省略 data 参数):

$(document).on("click", ".box", function () {
    alert(1);
});

从源码结构看,on() 之所以成为统一方案,是因为它内部整合了 bind(直接绑定)、delegate(委托绑定)和 live(全局委托)三种模式的参数处理,并且支持用空格分隔的事件名一次绑定多个事件。同时,这一套 on() 的 API 设计也被移动端库 Zepto 继承(51-Zepto入门.md 中 $('#btn').on('touchstart', function(){...}) 的写法与之完全一致),学透 on() 等于同时掌握了移动端事件绑定的基本范式。

off 方式解绑事件

$(selector).off();              // 解绑匹配元素的所有事件
$(selector).off("click");       // 解绑匹配元素的所有 click 事件
$(selector).off("click", "**"); // 解绑所有代理的 click 事件,元素本身的事件不会被解绑

注意第三行:"**" 表示匹配所有被委托的子元素选择器,用于精确清理通过 on() 挂载的委托事件,而不影响元素自身直接绑定的事件。

jQuery 的事件对象 Event

当事件触发时,jQuery 会把标准化后的 event 对象传给处理函数。常用属性与方法如下:

属性/方法 说明
event.data 传递给事件处理程序的额外数据(即 on() 的第三个参数)
event.currentTarget 等同于 this,当前 DOM 对象
event.pageX 鼠标相对于文档左部边缘的位置
event.target 触发事件源,不一定 === this(如在事件委托中,target 是实际被点击的后代元素)
event.stopPropagation() 阻止事件冒泡
event.preventDefault() 阻止默认行为
event.type 事件类型:click、dblclick……
event.which 鼠标的按键类型:左 1、中 2、右 3
event.keyCode 键盘按键代码

代码演示(绑定在 document 上的 click,打印各属性):

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="jquery-1.11.1.js"></script>
    <script>
        $(function () {
            $(document).on("click", {}, function (event) {
                console.log(event.data);
                console.log(event.currentTarget);
                console.log(event.target);
                console.log(event.pageX);
                console.log(event.type);
                console.log(event.which);
                console.log(event.keyCode);
            });
        })
    </script>
</head>
<body>

</body>
</html>

单击网页后,控制台会依次打印出 event.data(空对象 {})、event.currentTarget(document)、event.target(实际点击的元素)、event.pageX(鼠标横坐标)、event.type("click")、event.which(1,左键)、event.keyCode(click 事件下为 0)。

关于 event.target 与 event.currentTarget 的区别,结合 47-jQuery的介绍和选择器.md 中「jQuery 对象绑定的事件中,this 指 js 中的 DOM 对象」的说明可以这样理解:在事件委托场景下,currentTarget(即 this)是绑定事件的元素,而 target 是真正触发事件的深层元素,两者往往不同,这是事件委托排错时的关键检查点。

举例:按下键盘按键,页面变色

这个时候就要用到 event 参数,因为要获取 event.keyCode,才能知道按下的是键盘上的哪个按键。此案例与 44-键盘事件.md 中「通过 event 事件对象的 keyCode 来获取按键的编码」的原理完全一致。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .wrap {
            width: 400px;
            height: 400px;
            margin: 100px auto 0;
        }

        .wrap h1 {
            text-align: center;
        }

        .wrap div {
            width: 400px;
            height: 300px;
            background: pink;
            font-size: 30px;
            text-align: center;
            line-height: 300px;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        $(function () {
            //需求:在页面上,按键是哪个颜色的首写字母,div 就改变为该颜色,然后 span 内容赋值。
            var div = $("#bgChange");
            var span = $("#keyCodeSpan");

            //绑定事件
            $(document).keyup(function (e) {  //键盘弹起时,触发事件
                //调用方法
                setColor(e.keyCode);
            });

            function setColor(keyCode) {
                switch (keyCode) {
                    case 80:  // P -> pink
                        setEle("pink", keyCode);
                        break;
                    case 66:  // B -> blue
                        setEle("blue", keyCode);
                        break;
                    case 79:  // O -> orange
                        setEle("orange", keyCode);
                        break;
                    case 82:  // R -> red
                        setEle("red", keyCode);
                        break;
                    case 89:  // Y -> yellow
                        setEle("yellow", keyCode);
                        break;
                    default:
                        alert("系统没有设置该颜色!");
                }

                function setEle(a, b) {
                    div.css("background-color", a);
                    span.text(b);
                }
            }
        })
    </script>
</head>
<body>
<div class="wrap">
    <h1>按键改变颜色</h1>
    <div id="bgChange">
        keyCode为:
        <span id="keyCodeSpan">80</span>
    </div>
</div>
</body>
</html>

实现逻辑拆解:

  1. 给 document 绑定 keyup 事件(键盘弹起时触发,保证每个按键只触发一次,避免长按 keydown 的重复触发,这一点与 44-键盘事件.md 中「一直按着不松手,onkeydown 会一直触发」的提醒相呼应);
  2. 通过 e.keyCode 获取按键编码:P(80)→ pink、B(66)→ blue、O(79)→ orange、R(82)→ red、Y(89)→ yellow;
  3. 用 div.css("background-color", a) 修改背景色(css() 设置样式的用法见 49-jQuery操作DOM.md),用 span.text(b) 写入 keyCode 值。

jQuery 的两大特点

特点一:链式编程

比如 .show() 和 .html() 可以连写成 .show().html(),代码更简洁:

// 链式写法:show 之后再设置内容
$("div").show(1000).html("tomorrow!");

链式编程原理:return this。 通常情况下,只有设置操作才能把链式编程延续下去;因为获取操作的时候,会返回获取到的相应的值(string、number 等),无法返回 this,链条就此中断。这解释了为什么 $("div").height().css(...) 无法继续链式调用——height() 返回的是数字而不是 jQuery 对象。

链式编程中有一个重要的回溯方法:

end(); // 结束当前链最近的一次过滤操作,并且返回匹配元素之前的状态。

end() 在下面的「五角星评分」案例中发挥着关键作用。

特点二:隐式迭代

隐式对应的是显式。隐式迭代的意思是:在方法的内部会为匹配到的所有元素进行循环遍历,执行相应的方法,而不用我们再手动 for 循环,简化了操作。这正体现了 jQuery「write less, do more」的设计哲学——47-jQuery的介绍和选择器.md 中「jQuery 就是把 DOM 对象重新包装了一下,让其具有了 jQuery 方法」的结论,配合隐式迭代,使得 $("div").css("background", "pink") 一条语句即可作用于所有匹配的 div。

注意:如果获取的是多元素的值,大部分情况下返回的是第一个元素的值(例如前面提到的 css()、height() 获取场景)。

举例:五角星评分

综合运用链式编程、end() 回溯与事件机制:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>五角星评分案例</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        .comment {
            font-size: 40px;
            color: #ff3100;
        }

        .comment li {
            float: left;
            cursor: pointer;
        }

        ul {
            list-style: none;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        $(function () {
            var star_none = '☆'; // 空心五角星
            var star_sel = '★';  // 实心五角星

            //需求1:鼠标悬停时,当前的li和之前所有的li内容全部变为实心五角星,移开恢复为空心。
            $(".comment li").on("mouseenter", function () {
                //写法一:分两次写
//                $(this).text(star_sel).prevAll("li").text(star_sel);
//                $(this).nextAll("li").text(star_none);

                //写法二:一次性写完,但要用到 end(),否则会出问题。【重要】
                $(this).text(star_sel).prevAll("li").text(star_sel).end().nextAll("li").text(star_none);
            });

            $(".comment li").on("mouseleave", function () {
                //bug处理:如果没有点击过 li,那么会出现无法清除的现象,先判断是否已有 current 类
                if ($("li.current").length === 0) {
                    $(".comment li").text(star_none);
                } else {
                    //鼠标移开时,谁有 current 类名,那么当前和之前所有的 li 都是实心,后面的所有 li 都是空心
                    $("li.current").text(star_sel).prevAll("li").text(star_sel).end().nextAll("li").text(star_none);
                }
            });

            //需求2:鼠标点击某个 li,当前 li 和之前所有的 li 都变成实心,其他变为空心。
            $(".comment li").on("click", function () {
                //点击哪个 li 给它加一个类名,并清空其他所有 li 的类名
                $(this).attr("class", "current").siblings("li").removeAttr("class");
            });
        });
    </script>
</head>
<body>
<ul class="comment">
    <li>☆</li>
    <li>☆</li>
    <li>☆</li>
    <li>☆</li>
    <li>☆</li>
</ul>
</body>
</html>

上方代码中 end() 的用法很巧妙,需要重点理解这条链的执行过程:

$(this).text(star_sel)          // 当前 li 变实心
  .prevAll("li").text(star_sel) // 前面的所有 li 变实心(此时集合被过滤为 prevAll 的结果)
  .end()                        // 回到过滤之前的状态,即 $(this) 本身
  .nextAll("li").text(star_none); // 后面的所有 li 变空心

如果去掉中间的 .end(),那么最后一行的 .nextAll() 会基于 prevAll("li") 过滤后的集合继续操作,取到的是「前面那些 li 的后续兄弟」,逻辑就会出错——这正是链式编程中 end() 回溯的典型价值。同时案例也用到了 49-jQuery操作DOM.md 中的 attr("class", "current") 设置类名与 removeAttr("class") 移除类名,以及 siblings() 兄弟选择器(见 47-jQuery的介绍和选择器.md 的筛选选择器部分)。

each 的用法

大部分情况下是不需要使用 each() 方法的,因为 jQuery 自带隐式迭代特性。但是,如果要对每个元素做不同的处理(比如按顺序递增透明度),这时候就用到了 each() 方法。

格式如下:

$(selector).each(function (index, element) {});

参数解释:

  • 参数一 index:表示当前元素在所有匹配元素中的索引号(从 0 开始)。
  • 参数二 element:表示当前元素,是 js 中的 DOM 对象,而不是 jQuery 对象(若需使用 jQuery 方法,要先用 $(element) 包装)。

举例——让每个盒子透明度逐渐递增:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        li {
            width: 100px;
            height: 100px;
            margin: 20px;
            float: left;
            list-style: none;
            text-align: center;
            font: 50px/100px "simsun";
            color: white;
            background-color: black;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        jQuery(function () {
            //设置每个不一样的盒子透明度逐渐递增
            $("ul li").each(function (index, element) {
                $(element).css("opacity", (index + 1) / 10);
                console.log(index + "---" + element.tagName);
            });
        });
    </script>
</head>
<body>
<ul>
    <li class="aaa1">1</li>
    <li class="aaa2">2</li>
    <li class="aaa3">3</li>
    <li class="aaa4">4</li>
    <li class="aaa5">5</li>
    <li class="aaa6">6</li>
    <li class="aaa7">7</li>
    <li class="aaa8">8</li>
    <li class="aaa9">9</li>
    <li class="aaa10">10</li>
</ul>
</body>
</html>

运行后,10 个 li 的透明度依次为 0.1 → 1.0 渐变,控制台依次打印 0---LI、1---LI……这直观展示了 each() 与隐式迭代的差别:隐式迭代对所有元素执行「相同」的操作,而 each() 让每个元素可以根据 index 执行「不同」的操作。另外注意原生 element.tagName 返回的是大写标签名 LI,这也是「element 是 DOM 对象而非 jQuery 对象」的佐证。

多库共存

多库共存指的是:jQuery 占用了 $ 和 jQuery 这两个变量。当在同一个页面中同时引用了 jQuery 库以及其他的库(或者其他版本的 jQuery 库),恰好其他的库中也用到了 $ 或 jQuery 变量,此时要保证每个库都能正常使用,就产生了多库共存的问题。

温馨提示:可以通过以下方式获取 jQuery 库的版本号:

console.log($.fn.jquery);  // 打印 jQuery 库的版本号

$.fn 是 jQuery 的原型对象(所有 jQuery 方法挂载于此),$.fn.jquery 属性即当前库的版本字符串,可用于排查多库冲突时当前生效的版本。

办法一:让 jQuery 放弃对 $ 的使用权:

$.noConflict();

执行后,$ 变量被让出(交给页面上后加载的库,如另一版本的 jQuery),但当前 jQuery 库并没有放弃对 jQuery 关键字的使用权——之后只能通过 jQuery(...) 来调用该版本 jQuery 的功能。

办法二:同时放弃 $ 和 jQuery 两个符号的使用权,并定义一个新的使用权(当页面有三个库时,可以这样用):

$.noConflict(true);   // 返回值是新的关键字

noConflict(true) 会彻底释放 $ 和 jQuery 两个变量,其返回值就是新的调用关键字,可以这样接收:

var $j = $.noConflict(true);  // 之后用 $j 代替 jQuery 调用

这是多版本 jQuery 并存(例如老页面保留 1.x 兼容旧插件,同时引入新版)的标准解决方案。在 47-jQuery的介绍和选择器.md 中我们了解到 $ 本质上只是 jQuery 这个函数的别名(jQuery === $),理解了这一点,就能明白 noConflict() 的本质:释放别名,保留本体。

jQuery 的插件机制

jQuery 库虽然功能强大,但也不是面面俱到。jQuery 是通过插件的方式,来扩展它的功能:

  • 当你需要某个插件的时候,你可以「安装」到 jQuery 上面,然后使用;
  • 当你不再需要这个插件,就可以从 jQuery 上「卸载」它。

插件机制的核心是:插件本质上就是在 $.fn(jQuery 原型)上扩展新的方法,加载插件 JS 文件后,所有 jQuery 对象即可直接调用这些新方法,实现「按需安装、即插即用」。

插件之改变颜色:jQuery.color.js

jQuery 的自定义动画方法 animate() 在执行动画时,默认是不支持设置背景色 background-color 这个属性的(因为背景色不是数值型的可插值属性)。这个时候可以借助 jquery.color.js 这个插件来扩展支持。

举例:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: blue;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script src="jquery.color.js"></script>
    <script>
        $(function () {
            //点击按钮,改变盒子的宽度和背景色
            $("button").on("click", function () {
                $("div").animate({"width": 200, "background-color": "red"}, 2000, function () {
                    alert("动画结束");
                });
            });
        })
    </script>
</head>
<body>
<button>变色</button>
<div></div>
</body>
</html>

注意:插件必须放在 jQuery 库之后引入(顺序很重要):

<script src="jquery-1.11.1.js"></script>
<script src="jquery.color.js"></script>

否则在动画执行的过程中,是无法设置背景色的。其原理是:animate() 在执行时会对 CSS 属性做数值化解析(参见 48-jQuery动画详解.md 中自定义动画 $(selector).animate({params}, speed, callback) 的说明),jquery.color.js 为背景色这类颜色属性提供了「颜色插值」的底层支持,使其也能像 width、left 一样被逐帧平滑过渡。

插件之懒加载:jquery.lazyload.js

懒加载:当打开一个网页时,只有当我看到某个部分,再加载那个部分,而不是一下子全部加载完毕,这样可以优化页面的打开速度。通俗地说,设置了懒加载的图片,会等我「宠幸」到它的时候(滚动到可视区域),它再打开。

在 14-前端性能优化/lazyload&防抖动和节流阀.md 中对此有更深入的工程化解读:图片一般是页面最大的资源,所以非首屏延迟加载很重要(让首屏尽快显示);同时在 14-前端性能优化/04-静态资源优化.md 中也把「逐步加载图像:lazyload」列为静态资源优化的常用手段。可见懒加载不仅是 jQuery 时代的小技巧,更是前端性能优化的经典主题。

代码举例:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            height: 3000px;
            background-color: pink;
        }
    </style>
    <script src="jquery-1.11.1.js"></script>
    <!--懒加载的使用。第一步:导包(必须在 jquery 库的下方)-->
    <script src="jquery.lazyload.js"></script>
    <script>
        $(function () {
            //第二步骤:调用懒加载的方法实现功能。参数的不同,功能也不同。
            $("img.lazy").lazyload();
        })
    </script>
</head>
<body>
<div></div>
<!--需要实现将图片设置为懒加载模式-->
<img class="lazy" data-original="images/01.jpg" width="640" height="480">
</body>
</html>

使用要点:

  1. 导包顺序:jquery.lazyload.js 必须放在 jQuery 库的下方(与 jquery.color.js 同理,插件依赖 jQuery 环境);
  2. 关键属性:图片的 class="lazy" 用于选择器匹配,真实的图片地址写在 data-original 属性中(而不是 src),这样页面初始加载时不会请求真实图片;当图片滚动进入可视区域时,lazyload 插件才把 data-original 的值赋给 src 触发加载——这与 14-前端性能优化/05-页面渲染性能优化.md 中「把页面上懒加载元素 src 属性设置为空字符,把真实的 src 写在 data-lazy 属性中,滚动进入可视区域再赋值」的通用实现思路一致;
  3. 调用方式:$("img.lazy").lazyload(),参数不同功能不同(可配置加载阈值、淡入效果、占位图等)。

小结

本篇围绕 jQuery 的「事件机制与进阶知识」梳理了完整知识链:

  • 尺寸与坐标:height()/width() 返回 number 便于计算,offset() 相对 document(可设置,自动补 relative 定位),position() 相对有定位的父元素(只可获取),scrollTop()/scrollLeft() 控制滚动距离;
  • 事件机制:简写绑定(click/blur/mouseenter…)、on() 统一绑定(多事件、事件委托、传 data)、off() 解绑(含清理委托事件);
  • 事件对象:event.data、event.currentTarget、event.target、event.pageX、event.which、event.keyCode 等,并通过「按键变色」实战掌握键盘事件;
  • 两大特点:链式编程(return this + end() 回溯)与隐式迭代(内部自动遍历),配合五角星评分案例融会贯通;
  • 进阶技能:each() 做差异化遍历、$.noConflict() 解决多库共存、插件机制(jquery.color.js 扩展颜色动画、jquery.lazyload.js 实现图片懒加载)。

这些内容与 jQuery 系列其他篇章(47-jQuery的介绍和选择器.md 的 $ 符号与选择器、48-jQuery动画详解.md 的 show/hide/slideDown/stop 动画、49-jQuery操作DOM.md 的 css/类/节点/属性操作)互相印证,共同构成完整的 jQuery 前端知识体系。学完本篇后,你既可以用 on()/event 应对复杂交互,也能用链式编程写出简洁优雅的代码,还能借助多库共存与插件机制解决真实项目中的兼容与扩展问题。

登录后查看全文
Web