千古前端图文教程:jQuery 事件机制与进阶知识详解——从事件绑定、坐标操作到链式编程与插件扩展
千古前端图文教程: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>
实现逻辑拆解:
- 给
document绑定keyup事件(键盘弹起时触发,保证每个按键只触发一次,避免长按keydown的重复触发,这一点与 44-键盘事件.md 中「一直按着不松手,onkeydown 会一直触发」的提醒相呼应); - 通过
e.keyCode获取按键编码:P(80)→ pink、B(66)→ blue、O(79)→ orange、R(82)→ red、Y(89)→ yellow; - 用
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>
使用要点:
- 导包顺序:
jquery.lazyload.js必须放在 jQuery 库的下方(与jquery.color.js同理,插件依赖 jQuery 环境); - 关键属性:图片的
class="lazy"用于选择器匹配,真实的图片地址写在data-original属性中(而不是src),这样页面初始加载时不会请求真实图片;当图片滚动进入可视区域时,lazyload 插件才把data-original的值赋给src触发加载——这与 14-前端性能优化/05-页面渲染性能优化.md 中「把页面上懒加载元素 src 属性设置为空字符,把真实的 src 写在 data-lazy 属性中,滚动进入可视区域再赋值」的通用实现思路一致; - 调用方式:
$("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 应对复杂交互,也能用链式编程写出简洁优雅的代码,还能借助多库共存与插件机制解决真实项目中的兼容与扩展问题。