jQuery

为什么要学 jQuery

究其原因是因为原生 js 在进行 dom 操作时代码量多而且容错性差,不够简练。那么 jQuery 就是为了解决这些问题而出现的。

jQuery 是什么

jQuery 是一个快速、简洁的 JavaScript 框架。jQuery 设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装 JavaScript 常用的功能代码,提供一种简便的 JavaScript 设计模式,优化 HTML 文档操作、事件处理、动画设计和 Ajax 交互。
在此阶段,我们主要介绍如何来使用 jQuery 操作 DOM,其实就是学习 jQuery 封装好的那些功能方法,这些方法叫做 API(Application Programming Interface 应用程序编程接口)。

jQuery 的引入

  1. 下载到本地

    • 获取源文件

    • 引入页面

    • 1
      2
      3
      4
      // 先下载jQuery源文件
      // 引入
      // 同时注意引用顺序,引入之后才能使用,否则会报错 $ is not defined
      <script src="jquery-3.6.0.min.js" />
  2. CDN引入

jquery.js 和 jquery.min.js 的区别:

jquery.js是完整的未压缩的jQuery库,文件比较大,一般用于阅读学习源码或修改源码,一般不用于线上项目。

jquery.min.js是由完整版的jQuery库经过压缩得来,压缩后功能与未压缩的完全一样,只是将其中的空白字符、注释、空行等与逻辑无关的内容删除,并进行一些优化。这个版本一般用于网站引用使用,减小文件体积,降低网站流量,提升访问速度等。

版本选择

jQ 大体分为三个版本:1.xx 、 2.xx 、 3.xx,三个版本对比如下:

版本号 说明
1.xx 版本 兼容 IE678;不再更新;插件多;
2.xx 版本 不兼容 IE678;不再更新;插件少;
3.xx 版本 不兼容 IE678;仍在更新;插件少;

1.xx 版本优点在于支持 IE678,可以做浏览器兼容,插件是最丰富的的。1.7 之前的 1.x.x 版本与现在的高版本API相差较大,且选择器等各方面性能不高,因此推荐使用选用 1.7 之后的 1.x.x 版本。

2.x.x 版本相较于第一版没有增加什么新特性,主要是去除了对 IE678 的支持,提升了性能,减小了体积。

3.x.x 版本相较于之前版本,增加、删除、更改一些属性。

可以通过 $.fn.jquery 来查看相应的 jQuery 版本。

选择器

$、jQuery

jQ 提供了两个变量 $jQuery 给开发者使用,一般情况下使用 $ 变量即可;如果遇见其它库提供了 $ 变量,未防止冲突,可以使用 jQuery 变量。

用法

$(selector/fn)

参数

  • selector:选择内容
  • fn:函数

入口函数

以函数作为参数时,作用相当于页面的入口函数,当页面内容加载完成后执行接受的函数。

window.onload 的区别:

  • 执行时间

    • window.onload 必须等到页面内包括图片的所有元素加载完毕后才能执行。

    • $(function(){} 是 DOM 结构绘制完毕后就执行,不必等到加载完毕。因此执行时间比上面的快。

  • 编写个数

    • window.onload 只能设定一个
    • jQ 入口函数可以同时编写多个,并且都可以得到执行。

jQuery 的基本选择器

符号 说明
$(‘#demo’) 选择 id 为 demo 的元素
$(‘.demo’) 选择 class 为 demo 的所有元素
$(‘div’) 选择所有 div 标签元素
$(‘*‘) 选择所有标签元素
$(‘.arr.arr-left’) 选择同时具有 arr 和 arr-left 类名的元素

jQuery 的其他选择器

层级选择器

符号 说明
空格 后代选择器
> 子代选择器
+ 紧邻选择器
~ 兄弟选择器

属性选择器

符号 说明
$(‘a[href]’) 具有 href 属性的 a 标签
$(‘a[href=’baidu’]’) href 属性为’baidu’的 a 标签
$(‘a[href!=’baidu’]’) href 属性不为’baidu’的 a 标签,包括不具有 href 属性的 a 标签
$(‘a[href^=’www’]’) href 属性以’www’开头的 a 标签
$(‘a[href$=’cn’]’) href 属性以’cn’结尾的 a 标签
$(‘a[href*=’i’]’) href 属性包含’i’的 a 标签
$(‘a[href][title=’内容’]’) 具有 href 属性且 title 属性为’内容’的 a 标签

基本筛选选择器

符号 说明(index 从 0 开始)
:eq(index) 匹配一个给定索引值的元素
:gt(index) 匹配所有大于给定索引值的元素
:lt(index) 匹配所有小于给定索引值的元素
:odd 匹配所有索引值为奇数的元素
:even 匹配所有索引值为偶数的元素
:first 获取匹配的第一个元素
:last 获取匹配的最后一个元素

其他选择器

符号 说明(index 从 0 开始) 用法
:empty 匹配所有不包含子元素或者文本的空元素 $(‘li:empty’)
:contains(text) 匹配包含给定文本的元素 $(‘li:contains(‘john’)’)

以上方式除基本筛选选择器外选择元素效果与在CSS使用时效果一致,不在一一演示。

jQuery 对象

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<button>
按钮
</button>

<ul>
<li>li_1</li>
<li>li_2</li>
<li>li_3</li>
<li>li_4</li>
<li>li_5</li>
<li>li_6</li>
</ul>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $lis = $("li");
var $btn = $("button");
console.log($lis); // $.fn.init [li, li, li, li, li, li]
console.log($btn); // $.fn.init [button, xxx]
</script>

如上例可知:通过 $(选择器) 可以获取到选择器内容对应的 jQ 对象,jQ 对象是由符合选择器条件的所有 DOM 元素组成的伪数组。

我们可以接受 DOM 对象作为参数将其转化为 jQ对象:

1
2
3
var ulEle = document.querySelector("ul");
// 将ulEle 转换为 jQ对象
console.log($(ulEle)); // $.fn.init [ul]

如果我们想把 jQ 对象包含的 DOM 对象取出,只需对应数组下标取值即可:

1
2
3
4
5
6
7
// 获取第三个li DOM元素
console.log("第三个li DOM元素", $lis[2]); // <li>li_3</li>
// 获取button元素
console.log("获取button元素", $btn[0]); // <button>按钮</button>

var btn = document.querySelector("button");
console.log($btn[0] === btn); // true

jQ 还提供了 $ele.get(index) 的方法让我们获取其中的 DOM 元素:

1
2
// 获取第三个li DOM元素
console.log("第三个li DOM元素", $lis.get(2)); // <li>li_3</li>

为了区分 jQ 元素与 DOM 元素,防止使用方法不当。业界常用方法是使用 $ 作为变量名的前缀修饰获取的 jQ 元素。如上面例子中的 $btn 指代获取的 jQ 对象,btn 指获取的 DOM 对象。

注:因为获取 jQ 对象的方法本质上是调用函数,因此通常使用变量来获取经常使用 jQ 对象,而不是每次都使用  $(selector) 去选择。

不推荐写法::

1
2
3
$(".box").css("width", 100);
$(".box").addClass("d1");
$(".box").attr("title", "hello");

推荐写法:

1
2
3
4
var $box = $(".box");
$box.css("width", 100);
$box.addClass("d1");
$box.attr("title", "hello");

jQuery 对象操作

筛选关系节点

属性 说明
eq(index) 获取当前 jQ 数组中下标为 index 的 jQ 对象
find 返回符合条件的 jQ 对象的子节点
parent 返回 jQ 对象的父节点
children 返回 jQ 对象的所有子节点
prev 返回 jQ 对象上一个兄弟节点
prevAll 返回 jQ 对象的前面所有的兄弟节点
next 返回 jQ 对象下一个兄弟节点
nextAll 返回 jQ 对象后面所有的兄弟节点
siblings 返回当前 jQ 对象所有的兄弟节点

还有 prevUntilnotslice…等等方法,更多请自行查阅 jQ 文档。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<ul>
<li>li_1</li>
<li>li_2</li>
<li class="act">li_3</li>
<li>li_4</li>
<li>li_5</li>
<li>li_6</li>
</ul>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
// 获取li jQ数组
var $lis = $("li");

var $li4 = $("li").eq(3);
console.log("第四个li", $li4);

var $prev = $li4.prev();
console.log("第三个li元素", $prev);

var $next = $li4.next();
console.log("第五个li元素", $next);

var $lisLess4 = $li4.prevAll();
console.log("第四个前面的所有li", $lisLess4);

var $lisMore4 = $li4.nextAll();
console.log("第四个后面的所有li", $lisMore4);

var $siblings = $li4.siblings();
console.log("除第四个li之外所有的li", $siblings);

var $ul = $li4.parent()
console.log("根据parent选择到ul元素", $ul);

var $find = $ul.find(".act");
console.log("根据find查找带有act类名的li", $find);

console.log("ul的子节点获取", $ul.children());
</script>

样式操作

1
2
3
4
5
6
7
$ele.css("样式名") 获取元素的样式
$ele.css("样式名", "样式值") 设置单个元素样式
$ele.css({ 一次设置多个元素的样式
"样式名": "样式值",
"样式名": "样式值",
"样式名": "样式值"
})

提示:当设置带单位的值时,可以省略单位。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<style>
.box {
font-size: 36px;
}
</style>
<body>
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

$box.css("width", "300px");

// 当设置带单位的值时,可以省略单位
$box.css("height", 200);

$box.css({
position: "absolute",
top: 50,
left: 50,
backgroundColor: "#f00"
})

console.log("获取宽度", $box.css("width"));
console.log("获取字体大小", $box.css("font-size"));
</script>
</body>

属性操作

1
2
3
4
5
6
7
8
9
10
11
$ele.attr("属性名") 获取属性值
$ele.attr("属性名", "属性值") 设置单个属性
$ele.attr({ 设置多个属性值
"属性名": "属性值",
"属性名": "属性值",
"属性名": "属性值",
"属性名": "属性值"
})
$ele.removeAttr("属性名") 删除属性

attr 可以更换为 prop

区别:

  • attr 设置的非官方定义属性会出现在元素标签上,prop 设置的非官方定义属性会出现在元素对象上
  • attr 获取表单选择属性返回设置的值,prop 获取表单选择属性返回 boolean

注意:attr、prop设置的自定义属性不能通过对方获取

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div class="box"></div>
<input type="checkbox" checked="checked">

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

$box.attr("class", "d1 d2");
$box.prop("title", "hello world");
$box.attr("style", "width: 300px;height: 300px;background-color: #f00");

// 设置非官方定义属性
$box.attr("aaa", 0);
$box.prop("ccc", 0);

console.log("互相获取", $box.prop("aaa")); // undefined
console.log("互相获取", $box.attr("ccc")); // undefined

console.log("各自获取", $box.attr("aaa")); // 0
console.log("各自获取", $box.prop("ccc")); // 0

$box.removeAttr("aaa"); // 删除属性
$box.removeProp("ccc"); // 删除属性
console.log("删除后获取", $box.attr("aaa")); // undefined
console.log("删除后获取", $box.prop("ccc")); // undefined

var $ipt = $("input");

// 双击页面获取多选框是否被选中的属性值
window.ondblclick = function (){
console.log("attr获取", $ipt.attr("checked"));
console.log("prop获取", $ipt.prop("checked"));
}
</script>

类名操作

1
2
3
4
$ele.addClass() 向被选元素添加一个或多个类
$ele.removeClass() 从被选元素删除一个或多个类
$ele.hasClass() 判断被选元素是否存在类
$ele.toggleClass() 对被选元素进行添加/删除类的切换操作

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

$box.addClass("b1 b3 b2");
console.log($box.prop("class")); // box b1 b3 b2

$box.removeClass("b1 b3");
console.log($box.prop("class")); // box b2

$box.toggleClass("b2");
console.log($box.prop("class")); // box
console.log("b2存在否", $box.hasClass("b2")); // false

$box.toggleClass("b2");
console.log($box.prop("class")); // box b2

console.log("b2存在否", $box.hasClass("b2")); // true
</script>

常见的元素操作

添加元素

方法 作用
before 在 jQ 对象之前插入内容
prepend 在 jQ 对象的第一个子节点之前插入内容
append 在 jQ 对象的最后一个子节点之后插入内容
after 在 jQ 对象之后插入内容
replaceWith 使用内容替换该 jQ 对象

方法参数:DOM节点、字符串、jQ对象

注意:如果被插入内容是某个已经拥有父节点的节点,在被传递给此方法后,它首先会被移除,再被插入到新的位置。

还有 appendToprependTo…等等方法,更多请自行查阅 jQ 文档。

克隆节点

方法:$ele.clone(是否克隆jQ添加的事件)

删除节点

方法:$ele.remove()

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div class="box">疑似地上霜</div>

<h2>=================</h2>
<p>窗前明月光</p>
<span>举头望明月</span>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");
// 参数为:标签字符串。给元素之前添加静夜思标题,方法会解析标签
$box.before("<h2>静夜思</h2>");
// 参数为:DOM元素。给元素第一行添加DOM元素,页面上已经存在的p标签会消失,被移动到box元素中
$box.prepend(document.querySelector("p"));
// 参数为:jQ对象,页面上span元素会消失,被移动到box元素中
$box.append($("span"));
// 参数为:字符串。添加一行普通文本
$box.after("低头思故乡");
// 将box元素中的 span标签替换为p标签
$("span").replaceWith("<p>举头望明月</p>");

// jQ方式绑定事件,下面会提到,这里做演示使用
$box.click(function (){
console.log("aaa");
})
// 克隆box元素,点击事件也会生效,点击克隆的元素,也会在控制台输出 aaa
var $clone = $box.clone(true);
$("body").append($clone);

// 移除克隆元素
$clone.remove();
</script>

元素内容操作

方法 说明
$ele.html() 获取或设置元素内容HTML字符串
$ele.text() 获取或设置元素内容文本字符串
$input.val() 获取或设置input输入框的value值

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="box">
黄河之水天上来
<span>奔流到海不复回</span>
</div>

<input type="text" value="input 内容">

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");
var $ipt = $("input");

// 取值
console.log("html文本", $box.html());
console.log("text文本", $box.text());
console.log("value", $ipt.val());

// 赋值
$box.html("<p>hello world</p>");
// $box.text("<p>作为普通文本</p>");

$ipt.val("设置input输入框的值");
</script>

jQuery 事件

在 jQ 中,事件绑定通过两种方式:

  1. jQ对象.事件名(参数)
  2. jQ对象.on(事件名,其它参数)

在 jQuery 1.7 之后,统一使用 on 方法提供绑定事件处理程序所需的所有功能。旧的jQuery事件绑定方法如 .bind(), .delegate(), 和 .live() 等不再推荐使用。

常见的事件如:clickdblclickkeydownmouseoverchange等都可以使用第一种方式绑定事件,但也有特殊的如输入框的 input 事件等不支持第一种方式。具体的支持事件列表请参见 jQuery 官方文档。

事件对象

jQ 事件中的事件对象通过事件处理函数的形参获取,事件中的 eventwindow 上的属性,与原生事件中的事件对象一致。

jQ 事件对象常用属性也与之前学过的 DOM 事件对象几乎一致,多了一个 data 属性用于获取事件绑定时传入的参数。

事件中的 this

jQ 事件中的 this 指向绑定事件的 jQ 对象代表的 DOM 对象,如果使用 on 方式添加的事件委托,委托事件处理函数中的 this 指向委托元素的 DOM 对象。

事件特点

jQuery 允许给同一个 jQ 对象的同一个事件绑定多个不同的事件处理函数

直接绑定事件

语法

$ele.事件名([data], [fn])

参数

  • data:供函数使用的参数对象
  • fn:事件处理函数

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<button>点我文字颜色变蓝</button>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $btn = $("button");

$btn.click(function(){
$btn.css("color", "#00f");
})

// 绑定第二个相同事件
$btn.click({ data: "这是传入的参数" }, function(e){
console.log(e.data); // { data: "这是传入的参数" }
console.log(e); // 这是 jQ 的事件对象
console.log(event); // 这是 window 的事件对象,即我们之前讲过的
})
</script>

on 方式绑定事件

语法

1
$ele.on(type, [selector], [data], fn)

参数

  • type:事件名,可以是一个或者多个。
  • selector:一个选择器字符串,委托事件的元素选择器,可选。
  • data:事件参数,可选。
  • fn:该事件被触发时执行的函数。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<style>
button.act {
padding: 10px 20px;
}
</style>

<body>
<ul>
<li><p>li_1</p></li>
<li><p>li_2</p></li>
<li><p>li_3</p></li>
<li><p>li_4</p></li>
<li><p>li_5</p></li>
<li><p>li_6</p></li>
</ul>

<button>添加li</button>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $ul = $("ul");
var $btn = $("button");

// 点击按钮添加li
$btn.on("click", function (){
$ul.append(`<li>li_${ $ul.children().length + 1 }</li>`);
});

// 绑定具名函数
$btn.on("click", clickHandle);
function clickHandle(){
console.log("声明函数作为点击事件处理函数");
}

// on方式允许同时绑定多个不同类型的事件
$btn.on("mouseenter mouseleave", function (){
$(this).toggleClass("act");
})

// 使用事件委托,点击li让颜色变红
$ul.on("click", "li", function (){
this.style.color = "#f00";
})
</script>
</body>

off 解绑事件

jQ 使用 $ele.off() 方法移除给当前对象绑定的事件处理函数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在上例的JS中添加内容

// 取消 button 上绑定的所有事件
$btn.off();

// 取消一类特定的事件
// $btn.off("click");

// 取消特定事件的具名处理函数
// $btn.off("click", clickHandle);

// 取消事件委托
// $ul.off("click", "li");

jQuery 特性

链式调用

原理:每次执行完函数都会返回调用函数的 jQ 对象,这样可以在函数调用之后继续使用该对象的其它方法。

例:

1
2
3
4
5
6
7
8
9
10
11
12
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(".box").click(function() {
$(this)
.css("width", "80px")
.attr("title", "box")
.addClass("d1")
.toggleClass("d2");
});
</script>

需要注意的是在链式操作过程中 jQ 对象会转移,不一定是初始调用函数的对象。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="box">box</div>
<h2>hello world</h2>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(".box").click(function() {
$(this)
.css("width", "80px")
.attr("title", "box")
.next() // 此函数返回 $h2 对象
.addClass("title")
.css("color", "#f00")
});
</script>

运行之后发现 h2 标题的类名增加了 title,且字体颜色变红了。这是因为我们使用了 next 方法获取了 box 元素的下一个兄弟节点,之后的操作对象就变成了 h2 对象。

如果希望对象转移后在返回转移前的对象可以使用 end() 方法:

1
2
3
4
5
$(".box") // 当前返回$box
.next() // 返回 $h2
.addClass("title")
.end() // 将 $h2 换回 $box
.css("color", "#f00")

隐式迭代

jQ 对象是有符合筛选条件的 DOM 元素组成的伪数组,为该 jQ 对象添加的任何方法,都会在方法的内部会遍历节点数组,为其中的每一个的元素执行相应的方法。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<scipt>
$("li").css("color", "#f00"); // 每一个li的颜色都会改成红色
</scipt>
</body>
</html>

jQuery 动画

jQuery animate() 方法允许我们创建自定义的动画

语法

$(selector).animate(stylesObj,[duration],[timing-function],[callback])

参数

  • stylesObj:要执行动画的 CSS 属性与它设定的终点值组成的对象
  • duration:执行动画时长,值为三种预定速度之一的字符串(“slow”、”normal”、”fast”)或表示动画时长的毫秒数值(可选)
  • timing-function:动画运动速率函数,只有两个值: swinglinear(可选)
  • callback:动画执行完后立即执行的回调函数(可选)

Tips:动画设定样式终点值时也可以不带单位。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<style>
.box{
position: absolute;
top: 50px;
left: 50px;
width: 150px;
height: 150px;
background-color: #f00;
}
</style>

<body>
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");
$box.click(function (){
// 样式值可以带单位,也可以不带单位
$(this).animate({
top: "150px",
left: 150,
width: 300,
height: 300,
opacity: .2
}, 2000, "swing", function(){
console.log("动画执行完成");
})
})
</script>
</body>

Tips:jQuery 动画允许将元素样式的属性值设置为 “show”、”hide” 或 “toggle”

1
2
3
4
5
$box.click(function (){
$(this).animate({
width: "toggle"
}, 2000)
})

动画插件

jQuery 不能给元素颜色样式添加动画,动画的速率曲线也只有两种,如果我们想要更改元素的颜色,或者添加更多样的运动轨迹效果,需要借助插件实现。

常见的两个插件为:jquery.color.jsjquery.easing.js。前者为 jQ 添加颜色动画,后者扩展了时序函数。

注意:插件的使用依赖于 jQuery,因此引入插件要在引入 jQuery 文件之后。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<style>
.box{
position: absolute;
top: 50px;
left: 50px;
width: 150px;
height: 150px;
background-color: #f00;
}
</style>

<body>
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-easing/1.4.1/jquery.easing.compatibility.min.js"></script>
<script>
var $box = $(".box");
$box.click(function (){
// 样式值可以带单位,也可以不带单位
$(this).animate({
top: "150px",
left: 150,
width: 300,
height: 300,
opacity: .2,
backgroundColor: "#00f"
}, 2000, "easeInOutBack", function(){
console.log("动画执行完成");
})
})
</script>
</body>

动画队列

jQuery 默认提供针对动画的队列功能。即如果我们在一个函数内给元素添加了多个 animate() 调用,jQuery 会创建包含这些方法调用的“内部”队列。然后逐一运行这些 animate 调用。

我们将上面的动画拆分成三个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$box.click(function (){
$(this).animate({
top: "150px",
left: 150,
backgroundColor: "#00f"
}, 2000, "easeInOutBack", function(){
console.log("第一阶段完结");
})

$(this).animate({
width: 500,
height: 300
}, 3000)

$(this).animate({
opacity: .2
}, 3000)
})

拆分之前动画过程是所有样式一起运动,直至终点。拆分之后动画过程会变成:元素先改变上左边距以及颜色 -> 然后改变宽高 -> 最后改变透明度

更改三个动画的书写顺序,动画执行顺序也会改变,但都是从上往下依次执行。

动画延时

jQuery 使用 $ele.delay(time) 来给一段动画添加延时效果。例如:

1
2
3
4
5
$box.click(function (){
$(this).delay(2000).animate({
opacity: .2
}, 3000)
})

执行代码会发现动画是 2s 后开始执行的。

停止动画

stop

描述:此方法用于在动画完成之前停止动画或效果。

语法:$ele.stop(stopAll, goToEnd)

参数:

  • stopAll:是否全部停止动画(清除队列中所有动画),默认 false。即仅停止活动的动画,允许任何排入队列的动画向后执行。
  • goToEnd:是否立即完成当前动画,即将当前动画的样式直接设置为终点值,默认 false

finish

此方法会立即停止动画队列中所有动画,并将元素样式设置为所有动画的终点值叠加后的状态,如果多个动画改变了同一个属性,以最后一个动画的结束样式为准。

语法: $ele.finish()

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<style>
.box{
position: absolute;
top: 50px;
left: 50px;
width: 150px;
height: 150px;
background-color: #f00;
}
</style>

<body>
<div class="box"></div>

<button>停止所有,并且停在最终点</button>
<button>停止当前动画,执行下一个动画</button>
<button>快进到当前动画的终点,执行下一个动画</button>
<button>停止所有动画,并且停在当下</button>
<button>快进到当前动画的终点,停止所有动画</button>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-easing/1.4.1/jquery.easing.compatibility.min.js"></script>
<script>
var $box = $(".box");
var $btns = $("button");

$box.click(function (){
$(this).animate({
top: "150px",
left: 150,
backgroundColor: "#00f"
}, 2000, "easeInOutBack", function(){
console.log("第一阶段完结");
})

$(this).animate({
width: 500,
height: 300
}, 3000)

$(this).animate({
top: 50,
opacity: .2
}, 3000)
})

$btns.eq(0).click(function (){
$box.finish();
})

$btns.eq(1).click(function (){
$box.stop(false, false);
})

$btns.eq(2).click(function (){
$box.stop(false, true);
})

$btns.eq(3).click(function (){
$box.stop(true, false);
})

$btns.eq(4).click(function (){
$box.stop(true, true);
})
</script>
</body>

快捷动画

动画名 说明
show 让元素出现
hide 隐藏元素
toggle 切换元素出现与隐藏
slideDown 元素滑入,类似放下卷门帘
slideUp 元素滑出,类似上卷门帘
slideToggle 切换元素的滑入滑出
fadeIn 元素渐现
fadeOut 元素渐隐
fadeToggle 切换元素的淡入淡出效果

上述方法均接受三个可选参数:durationtiming-functionfn,三个参数与 animate 动画的参数效果一致,不再赘述。

补充:还有一个 $ele.fadeTo(时长, 透明度) 的方法可以快捷的给元素添加透明度动画。

Tips:让元素出现和隐藏的动画默认是直接改变元素的 display 属性的,即闪现动画。添加上时间才能看到动画过程。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<style>
.box{
position: absolute;
top: 50px;
left: 50px;
width: 300px;
height: 300px;
background-color: #f00;
}
</style>
<body>
<div class="box"></div>

<button>show</button>
<button>hide</button>
<button>toggle</button>

<button>slideDown</button>
<button>slideUp</button>
<button>slideToggle</button>

<button>fadeIn</button>
<button>fadeOut</button>
<button>fadeToggle</button>

<button>fadeTo</button>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

$("button:eq(0)").click(function (){
$box.show(1000, function (){
console.log("出现了");
$box.animate({
backgroundColor: "#00f"
})
});
})
$("button:eq(1)").click(function (){
$box.hide(1000, function (){
console.log("消失了");
});
})
$("button:eq(2)").click(function (){
$box.toggle(1000);
})

$("button:eq(3)").click(function (){
$box.slideDown(1000);
})
$("button:eq(4)").click(function (){
$box.slideUp(1000);
})
$("button:eq(5)").click(function (){
$box.slideToggle(1000);
})

$("button:eq(6)").click(function (){
$box.fadeIn(1000);
})
$("button:eq(7)").click(function (){
$box.fadeOut(1000);
})
$("button:eq(8)").click(function (){
$box.fadeToggle(1000);
})

$("button:eq(9)").click(function (){
$box.fadeTo(1000, .2);
})
</script>
</body>

其它介绍

尺寸相关

我们可以使用 $ele.width()$ele.height() 方法来快速读取和设置元素的宽度和高度,获取的值是不带单位的 number 类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<style>
.box {
width: 200px;
height: 200px;
padding: 20px;
background-color: #f00;
}
</style>

<body>
<div class="box"></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

console.log("获取width", $box.width()); // 200
console.log("获取height", $box.height()); // 200

$box.onclick = function(){
// 赋值时可以带单位,也可以不带单位
$box.width("300px");
$box.height(300);
}
</script>
</body>

位置相关

position

此方法用于获取元素距离最近的具有定位的父元素的内容区的位置。效果等同于获取元素的 offsetLeftoffsetTop。此属性只能获取,不能设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<style>
.container {
position: relative;
margin: 50px;
padding: 50px;
width: 300px;
border: 20px solid #00f;
}
.box {
margin: 20px;
width: 50px;
height: 50px;
background-color: #f00;
}
</style>
<body>
<div class="container">
<div class="box"></div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

console.log("获取position", $box.position()); // { top: 70px; left: 70px }
</script>
</body>

offset

此方法可用于获取或设置元素相对于文档的位置。更改位置是通过调节元素的 top 属性和 left 属性达成的,为此元素需要有定位属性。如果元素没有定位属性,那么此操作会为元素添加 relative 定位属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<style>
.container {
position: relative;
margin: 50px;
padding: 50px;
width: 300px;
border: 20px solid #00f;
}
.box {
margin: 20px;
width: 50px;
height: 50px;
background-color: #f00;
}
</style>
<body>
<div class="container">
<div class="box"></div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $box = $(".box");

console.log("获取元素与页面的上左边距", $box.offset()); // { top: 120, left: 120 }

$box.click(function(){
// 设置元素与页面的上左边距各为 50
$box.offset({
top: 50,
left: 50
})
})
</script>
</body>

scrollTop/scrollLeft

用于获取匹配元素相对滚动条上左位置的偏移。此方法对可见和隐藏元素均有效。

这两个属性可以添加在 animate 动画中,实现动画效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<style>
body {
width: 3000px;
height: 3000px;
}
</style>

<body>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var $html = $("html");

window.onscroll = function (){
console.log("页面卷入上左边距", {
top: $html.scrollTop(),
left: $html.scrollLeft()
});
}

window.onclick = function (){
$("html").animate({
scrollTop: 0,
scrollLeft: 0
}, 1000, "swing")
}
</script>
</body>

多库共存

此处多库共存指的是:jQuery 占用了*$* 和 jQuery 这两个变量。当在同一个页面中引用了其他插件库中也用到了 *$*。那么,为了保证每个库都能正常使用,需要使用 $.noConflict() 方法让 jQuery 释放对 $ 的控制权,让其他库能够使用 $ 符号,达到多库共存的目的。

捶jQuery

2018年7月25日,Mislav Marohnić发了一条推文,宣布GitHub.com前端已经彻底删除了jQuery。而且,还自问自答地解释(低调炫耀),删除jQuery之后也没用其他框架,而是全部依赖原生API。

2018年7月27日奇舞周刊上推送了一篇文章:再见jQuery,我的老朋友,作者是07年最早翻译jQuery1.1文档的 为之漫笔。由此可见jQuery在前端疯狂发展的背景下正缓慢的流失生命力。

jQuery的辉煌

jQuery最初诞生于2006年8月,作者是John Resig(https://zh.wikipedia.org/wiki/JQuery)。10多年前,网页开发者(当时还没有“前端”这个概念)深受浏览器不兼容性之苦。以jQuery为代表的一批JavaScript库/框架应运而生:

  • Dojo
  • jQuery
  • MooTools
  • Prototype
  • Yahoo! User Interface Library (YUI)
  • Script.aculo.us

这些库有的像jQuery一样是主打通用性,比如Dojo、Prototype;有的则走更专业化的路线,比如YUI(组件化)和Script.aculo.us(动画交互)。从通用功能看,这些库大都提供了如下特性:

  • 语法糖:链式调用、实用函数
  • 选择元素:基于各种标准选择符和库自定义的选择符,以及通过回调进行筛选
  • 操作DOM:创建和操作元素,乃至各种属性操作
  • 处理事件:ready事件及各种注册和触发事件的方法,乃至委托
  • 动画:基于animate的CSS属性动画,以及内置动画方法
  • Ajax:封装原生的XMLHttpRequest API,简化请求方法及回调处理

一批宣传和推广这些库和框架的书籍相继面世,迅速推动了这些库的采用。2010年出版的DOM Scripting, 2nd(《JavaScript DOM脚本编程艺术(第2版)》)就是其中之一。这本书专门有一个附录,介绍当时流行的库,主推jQuery。

jQuery凭借其选择器方法、面向集合的链式调用、对事件和Ajax的完善支持、简单而强大的动效等独有优势,迅速风靡,成为几乎所有网站开发必备的JavaScript库,乃至开创了jQuery编程风格。

开发者选择jQuery的理由简单直接:

  • 跨浏览器
  • 简单高效
  • 稳定可靠
  • 插件丰富

2011年新版的“犀牛书”第6版——JavaScript: The Definitive Guide, 6th甚至拿出第19章整整64页篇幅隆重讲解了jQuery(“Chapter 19. The jQuery Library”)。

jQuery从此走向鼎盛和辉煌。后来,随着前端交互越来越重和移动应用的普及,jQuery UI、jQuery Mobile相继面世。

时至今日,jQuery仍然在支撑着数以千万计各种规模网站的运作——尽管聚光灯下已经不常看到她的身影。

历史的选择

最近10年,是“前端行业”有史以来发展最快的10年。

移动社交时代的到来不仅没有让桌面Web失色,反倒刺激了Web标准的迅猛改进。HTML5不仅带来了极大的向后兼容性,也带来了更丰富的原生DOM API。CSS从CSS3开始走上模块化的快车道,文本样式、排版布局、媒体查询,各种新模块让人目不暇接。

各大主流浏览器也在快速跟进,Firefox、Chrome、Opera、Safari、IE乃至Edge,都在积极重构甚至重写内核,争做支持Web标准的“楷模”。在这个大背景下,各大互联网公司不断调高兼容的IE版本号,从8到9到10,再到11。

当然,还有ECMAScript语言标准。自从划时代的ES6(ECMAScript 2015)发布之后,JavaScript终于真正开始摆脱“玩具”语言的尴尬境地。更重要的,从ES6起,ECMAScript也进入了快速迭代、每年发一版的节奏。ES7、ES8,以及ES9,每次都会给这门语言注入更强大的语言特性。

与此同时,Node.js和Babel等服务端运行时及转译工具的出现,也让前端工程化,以及向传统工业级软件开发最佳实践靠拢的速度日益加快。

2012年,图灵社区中一篇文章总结“JavaScript宝座:七大框架论剑”(http://www.ituring.com.cn/article/8108)。当时的“七大框架”是:

  • Backbone
  • Knockout
  • Spine
  • CanJS
  • Ember
  • AngularJS
  • Batman
  • Meteor

后来,谷歌主打SPA(Single Page Application,单页应用)的Angular终于一枝独秀。不久,脸书推出的“在JS里写HTML一样优雅”的React则一路高歌猛进。最终,集各家所长且简单易用的Vue横空出世。

前端开发已经从后“刀耕火种”时代的“农业文明”,逐渐进化为以大规模、可扩展、规范化、自动化为特征的准“工业文明”。

俗话说:“皮之不存,毛将焉附。”随着时代变迁、技术进步,jQuery赖以存在的环境正逐渐消失。如前所述,新的环境催生了一批框架新秀。曾经辉煌的jQuery终于走到了可以华丽谢幕的时刻。

尾声

如今,时移世易,jQuery即将谢幕,新一代组件化开发框架粉墨登场。然而,“太阳底下没有新鲜事。”不管是使用Angular,还是React,抑或是Vue,还是要真正理解它们背后的工作原理。

jQuery作为第一代前端库的优秀代表,成就了今天Web的繁荣,也成就了一代Web开发者。既不希望它离开,又希望它早点离开,这应该是很多早期接触jQuery的前端开发者的心声吧。