jQuery 是 JavaScript 中使用最广泛的一个库,它可以帮助我们简化 js 代码,更好的完成工作。
痛点
javascript 遇到的一些痛点:
window.onload
事件有个覆盖问题,我们只能写一个- 代码容错性差
- 浏览器兼容性问题
- 书写很繁琐,代码量多
- 代码很乱,各个页面到处都是
- 动画效果,我们很难实现
版本
目前jQuery有三个大版本:
1.x:兼容 ie678,使用最为广泛的,官方只做 BUG 维护,功能不再新增。因此一般项目来说,使用1.x版本就可以了,最终版本:1.12.4 (2016年5月20日)
2.x:不兼容 ie678,很少有人使用,官方只做 BUG 维护,功能不再新增。如果不考虑兼容低版本的浏览器可以使用 2.x,最终版本:2.2.4 (2016年5月20日)
3.x:不兼容 ie678,只支持最新的浏览器。除非特殊要求,一般不会使用3.x版本的,很多老的 jQuery 插件不支持这个版本。目前该版本是官方主要更新维护的版本。最新版本:3.3.1
引入
使用 jQuery 只需要在页面的 <head>
引入 jQuery 文件即可
1
2
3
4
5
6
7
8
9
| <html>
<head>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
...
</head>
<body>
...
</body>
</html>
|
$
符号
$
是著名的 jQuery 符号。实际上,jQuery 把所有功能全部封装在一个全局变量 jQuery 中,而 $
也是一个合法的变量名,它是变量 jQuery 的别名:
1
2
3
4
| window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'
|
jQuery入口函数
1
2
3
4
| //方法1:
$(document).ready(function(){});
//方法2:
$(function(){});
|
javascript 的入口函数和 jquery 的入口函数区别:
- javascript 的 window.onload 事件是等到所有内容,以及我们外部图片之类的文件加载完了之后,才会去执行。jQuery 入口函数是在 html 所有标签都加载进去后执行。
- jQuery 入口函数不会有被覆盖问题。
选择器
jQuery的基本选择器
符号 | 说明 |
---|
$("#demo") | 选择id为dem的第一个元素 |
$(".item") | 选择所有class=“item"的元素 |
$(“div”) | 选择所有div标签 |
$("*") | 选择所有元素(建议配合其他选择器使用) |
$(".item, div”) | 组合选择器(选择class=“item"和div选择器) |
$(“div span) | 交集选择器(选择div标签下的所有span标签) |
$(“div > span”) | 子元素选择器(选择div的子标签中的span标签(只是直接子标签)) |
$(“div + span”) | 相邻元素选择器(选择div相邻的span) |
层级选择器
如果两个 DOM 元素具有层级关系,就可以用 $('ancestor descendant')
来选择,层级之间用空格隔开。例如:
1
2
3
4
5
6
7
8
| <!-- HTML结构 -->
<div class="testing">
<ul class="lang">
<li class="lang-javascript">JavaScript</li>
<li class="lang-python">Python</li>
<li class="lang-lua">Lua</li>
</ul>
</div>
|
子选择器
子选择器 $('parent>child')
类似层级选择器,但是限定了层级关系必须是父子关系,就是 <child>
节点必须是 <parent>
节点的直属子节点。还是以上面的例子:
1
2
| $('ul.lang>li.lang-javascript'); // 可以选出[<li class="lang-javascript">JavaScript</li>]
$('div.testing>li.lang-javascript'); // [], 无法选出,因为<div>和<li>不构成父子关系
|
过滤器
过滤器一般不单独使用,它通常附加在选择器上,帮助我们更精确地定位元素。观察过滤器的效果:
1
2
3
4
5
6
7
| $('ul.lang li'); // 选出JavaScript、Python和Lua 3个节点
$('ul.lang li:first-child'); // 仅选出JavaScript
$('ul.lang li:last-child'); // 仅选出Lua
$('ul.lang li:nth-child(2)'); // 选出第N个元素,N从1开始
$('ul.lang li:nth-child(even)'); // 选出序号为偶数的元素
$('ul.lang li:nth-child(odd)'); // 选出序号为奇数的元素
|
jQuery 中的基本过滤选择器
符号 | 说明 |
---|
:eq(index) | index是从0开始,表示第index+1个匹配的元素 |
:gt(index) | 选择序号大于index的元素 |
:lt(index) | 选择序号小于index的元素 |
:odd | 序号为奇数的 |
:even | 序号为偶数的 |
:first | 选择第一个匹配的元素 |
:last | 选择最后一个匹配的元素 |
属性选择器
jQuery 中常用的属性选择器
符号 | 说明 |
---|
$(“a[href]") | 选择所有包含href属性的元素 |
$(“a[href=‘label’]") | 选择属性为href=“label"的元素 |
$(“a[href!=‘label’]") | 选择属性不是href=“label"的元素 |
$(“a[href^=‘label’]") | 选择所有href以label开头的元素 |
$(“a[href$=‘label’]") | 选择所有href以label结尾的元素 |
$(“a[href*=‘label’]") | 选择所有href中包含label的元素 |
$(“a[href][title=‘我’]") | 选择所有包含href属性并且title=“我"的元素 |
查找
通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个 jQuery 对象后,还可以以这个对象为基准,进行查找和过滤。
最常见的查找是在某个节点的所有子节点中查找,使用 find()
方法,它本身又接收一个任意的选择器。例如如下的 HTML 结构:
1
2
3
4
5
6
7
8
| <!-- HTML结构 -->
<ul class="lang">
<li class="js dy">JavaScript</li>
<li class="dy">Python</li>
<li id="swift">Swift</li>
<li class="dy">Scheme</li>
<li name="haskell">Haskell</li>
</ul>
|
用 find() 查找子节点
1
2
3
4
| var ul = $('ul.lang'); // 获得<ul>
var dy = ul.find('.dy'); // 获得JavaScript, Python, Scheme
var swf = ul.find('#swift'); // 获得Swift
var hsk = ul.find('[name=haskell]'); // 获得Haskell
|
用 parent() 查找父节点
1
2
3
| var swf = $('#swift'); // 获得Swift
var parent = swf.parent(); // 获得Swift的上层节点<ul>
var a = swf.parent('.red'); // 获得Swift的上层节点<ul>,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象
|
用 next() 和 prev() 查找同层级
1
2
3
4
5
6
7
| var swift = $('#swift');
swift.next(); // Scheme
swift.next('[name=haskell]'); // 空的jQuery对象,因为Swift的下一个元素Scheme不符合条件[name=haskell]
swift.prev(); // Python
swift.prev('.dy'); // Python,因为Python同时符合过滤器条件.dy
|
过滤
和函数式编程的 map、filter 类似,jQuery 对象也有类似的方法。
filter() 方法可以过滤掉不符合选择器条件的节点:
1
2
| var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var a = langs.filter('.dy'); // 拿到JavaScript, Python, Scheme
|
或者传入一个函数,要特别注意函数内部的 this 被绑定为 DOM 对象,不是 jQuery 对象:
1
2
3
4
| var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
langs.filter(function () {
return this.innerHTML.indexOf('S') === 0; // 返回S开头的节点
}); // 拿到Swift, Scheme
|
map() 方法把一个 jQuery 对象包含的若干 DOM 节点转化为其他对象:
1
2
3
4
| var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var arr = langs.map(function () {
return this.innerHTML;
}).get(); // 用get()拿到包含string的Array:['JavaScript', 'Python', 'Swift', 'Scheme', 'Haskell']
|
此外,一个 jQuery 对象如果包含了不止一个 DOM 节点,first()、last() 和 slice() 方法可以返回一个新的 jQuery 对象,把不需要的 DOM 节点去掉:
1
2
3
4
| var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var js = langs.first(); // JavaScript,相当于$('ul.lang li:first-child')
var haskell = langs.last(); // Haskell, 相当于$('ul.lang li:last-child')
var sub = langs.slice(2, 4); // Swift, Scheme, 参数和数组的slice()方法一致
|
DOM操作
直接使用浏览器提供的API对DOM结构进行修改,不但代码复杂,而且要针对浏览器写不同的代码。
有了jQuery,我们就专注于操作jQuery对象本身,底层的DOM操作由jQuery完成就可以了,这样一来,修改DOM也大大简化了。
添加DOM
要添加新的DOM节点,除了通过jQuery的html()这种暴力方法外,还可以用append()方法,例如:
1
2
3
4
5
6
7
| <div id="test-div">
<ul>
<li><span>JavaScript</span></li>
<li><span>Python</span></li>
<li><span>Swift</span></li>
</ul>
</div>
|
如何向列表新增一个语言?首先要拿到
节点:1
| var ul = $('#test-div>ul');
|
然后,调用append()传入HTML片段:
1
| ul.append('<li><span>Haskell</span></li>');
|
除了接受字符串,append()还可以传入原始的DOM对象,jQuery对象和函数对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // 创建DOM对象:
var ps = document.createElement('li');
ps.innerHTML = '<span>Pascal</span>';
// 添加DOM对象:
ul.append(ps);
// 添加jQuery对象:
ul.append($('#scheme'));
// 添加函数对象:
ul.append(function (index, html) {
return '<li><span>Language - ' + index + '</span></li>';
});
|
append()把DOM添加到最后,prepend()则把DOM添加到最前。
另外注意,如果要添加的DOM节点已经存在于HTML文档中,它会首先从文档移除,然后再添加,也就是说,用append(),你可以移动一个DOM节点。
同层级之间可以用用after()或者before()方法。
删除节点
remove方法
要删除DOM节点,拿到jQuery对象后直接调用remove()方法就可以了。如果jQuery对象包含若干DOM节点,实际上可以一次删除多个DOM节点:
1
2
| var li = $('#test-div>ul>li');
li.remove(); // 所有<li>全被删除
|
detach方法
detach()和remove()一样,是从DOM中去掉所有匹配元素,但是不会把jQuery对象中删除,所有关于该节点的事件、附加的数据都会保留下来。
empty方法
empty方法不是删除节点,而是清空元素中的所有后代节点。
复制节点
可用通过clone()方法来复制节点,clone()方法可以传一个boolean参数,如果传true表示复制元素的同时也复制元素中所绑定的事件。
1
| $(this).clone(true).appendTo("body");
|
替换节点
jQuery提供了replaceWith()和replaceAll()方法来替换节点
replaceWith()方法作用是将所有匹配的元素都替换成制定的html或者DOM元素。
1
| $("p").replaceWith("<strong>我会把你这个节点替换掉</strong>")
|
replaceAll()和replaceWith()的作用相同,知识颠倒了操作。
1
| $("<strong>我会把里面的所有你都替换掉</strong>").replaceAll("p");
|
包裹节点
1
| $("strong").wrap("<b></b>") //用b标签把<strong>元素包裹起来
|
包裹元素还有wrapAll()和wrapInner()方法, 与wrap()的区别如下:
1
2
3
4
5
6
| <strong>有线网络</strong>
<strong>无线网络</strong>
<ul>
<li>GY</li>
<li>NetChina</li>
</ul>
|
如果使用wrap()
1
2
3
4
5
| $("strong").wrap("<b></b>");
//结果
//<b><strong>有线网络</strong></b>
//<b><strong>无线网络</strong></b>
|
如果使用wrapAll()方法
1
2
3
4
5
6
7
| $("strong").wrapAll("<b></b>");
//结果
//<b>
// <strong>有线网络</strong>
// <strong>无线网络</strong>
//</b>
|
如果用wrapInner()方法
1
2
3
4
5
| $("strong").wrapInner("<b></b>");
//结果
//<strong><b>有线网络</b></strong>
//<strong><b>无线网络</b></strong>
|
插入节点
方法 | 描述 |
---|
append() | 匹配元素内部追加(父子节点) |
appendTo() | 和append()颠倒A.appendTo(B) == B.append(A) |
prepend() | 匹配元素内部最前面插入 |
prependTo() | A.prependTo(B) == B.prepend(A) |
after() | 在匹配元素之后插入(兄弟节点) |
insertAfter() | A.inertAfter(B) == B.after(A) |
before() | 在匹配元素之前插入(兄弟节点) |
insertBefore() | A.intertBefore(B) == B.before(A) |
DOM对象和jQuery对象切换
在jQuery对象中无法使用DOM对象的任何方法,可以用jQuery类似的方法代替,DOM对象也不能使用jQuery的方法。
$(dom对象) ==> jQuery对象
$("#btn”)[0] 或者 $("#btn”).get(0) ==> DOM对象
下拉菜单Demo
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
| <div class="wrap">
<ul>
<li><a href="#">一级菜单1</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
<li><a href="#">一级菜单2</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
<li><a href="#">一级菜单3</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
</ul>
</div>
|
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
29
30
31
32
33
34
35
36
37
38
39
40
41
| *{padding: 0; margin: 0;}
ul{
list-style: none;
}
.wrap{
width: 331px;
height: 30px;
margin: 100px auto 0;
background: #888;
padding-left: 10px;
border-radius: 4px;
}
.wrap li{
float: left;
width: 100px;
height: 30px;
margin-right: 10px;
position: relative;
}
.wrap a{
color: black;
text-decoration:none;
display:block;
width: 100px;
height: 28px;
text-align: center;
line-height: 28px;
background: #FFCF00;
border-radius: 6px;
border:1px solid #FF8626;
color: #666;
}
.wrap li ul{
position: absolute;
display: none;
}
|
js实现
1
2
3
4
5
6
7
8
9
| $(document).ready(function(){
$(".wrap li").mouseenter(function(){
$(this).children("ul").show();
});
$(".wrap li").mouseleave(function(){
$(this).children("ul").hide();
});
});
|
mouseover/mouseout和mouseenter/mouseleave区别
mouseover其中的所有元素进入都会事件触发一次, mouseenter只会触发一次,所以上面使用的是mouseenter.
三种变体写法
第一种:
1
2
3
4
5
| $(".wrap li").hover(function(){
$(this).children("ul").show();
}, function(){
$(this).children("ul").hide();
})
|
第二种:
1
2
3
4
5
6
7
8
9
| $(".wrap li").hover(function(){
var $this = $(this).children("ul");
var isShow = $this.css("display");
if(isShow === "block"){
$this.hide();
}else{
$this.show();
}
});
|
第三种:
1
2
3
| $(".wrap li").hover(new function(){
$(this).children("ul").slideToggle();
});
|
slideToggle()方法是在显示和隐藏之间切换的动画。
本文部分内容参考自廖雪峰的官方网站