目录
一、使用jQuery
二、jQuery基础选择器
按ID查找
按标签查找
按class查找
按属性查找
组合查找
多项选择器
练习
层级选择器(Descendant Selector)
子选择器(Child Selector)
过滤器(Filter)
表单相关
练习
查找
DOM操作
过滤
练习
添加DOM
删除节点
练习
鼠标事件
键盘事件
其他事件
事件参数
取消绑定
事件触发条件
jQuery是JavaScript世界中使用最广泛的一个库。
jQuery能帮我们干这些事情:消除浏览器差异/简洁的操作DOM的方法/轻松修改CSS等各种操作。
jQuery的理念“Write Less, Do More“,让你写更少的代码,完成更多的工作!
使用jQuery只需要在页面的引入jQuery文件即可:
...
...
$符号
$
是著名的jQuery符号。实际上,jQuery把所有功能全部封装在一个全局变量jQuery
中,而$
也是一个合法的变量名,它是变量jQuery
的别名:
window.jQuery;
// jQuery(selector, context)
window.
$
;
// jQuery(selector, context)
$ == jQuery;
// truetypeof($);
// 'function'
选择器是jQuery的核心。一个选择器写出来类似$('#dom-id')
。
jQuery的选择器就是帮助我们快速定位到一个或多个DOM节点 (页面标签)。
如果某个DOM节点有id
属性,利用jQuery查找如下:
//
查找
id="abc">:
var
$
div = $('#abc');
注意,
#abc
以#
开头。返回的对象是jQuery对象。什么是jQuery对象?jQuery对象类似数组,它的每个元素都是一个引用了DOM节点的对象。
以上面的查找为例,如果
id
为abc
的
存在,返回的jQuery对象如下:[
id="abc">...]如果
id
为abc
的
不存在,返回的jQuery对象如下:[]
总之jQuery的选择器不会返回
undefined
或者null
,这样的好处是你不必在下一行判断if (div === undefined)
。jQuery对象和DOM对象之间可以互相转化:
vardiv = $(
'#abc');
// jQuery对象vardivDom = div.get(
0);
// 假设存在div,获取第1个DOM元素varanother = $(divDom);
// 重新把DOM包装为jQuery对象通常情况下你不需要获取DOM对象,直接使用jQuery对象更加方便。如果你拿到了一个DOM对象,那可以简单地调用
$(aDomObject)
把它变成jQuery对象,这样就可以方便地使用jQuery的API了。按标签查找
按tag查找只需要写上tag名称就可以了:
var ps = $('p'); //
返回所有
节点
ps.length; //
数一数页面有多少个
节点
按class查找
按class查找注意在class名称前加一个
.
:var a = $('.red'); //
所有节点包含`class="red"`都将返回
//
例如:
//
class="red">...
//
class="green red">
...
通常很多节点有多个class,我们可以查找同时包含
red
和green
的节点:var a = $('.red.green'); //
注意没有空格!
//
符合条件的节点:
//
class="red green">...
//
class="blue green red">...
按属性查找
一个DOM节点除了
id
和class
外还可以有很多属性,很多时候按属性查找会非常方便,比如在一个表单中按属性来查找:var email = $('[name=email]'); //
找出
?? name="email">var passwordInput = $('[type=password]'); // 找出?? type="password">
var a = $('[items="A B"]'); // 找出?? items="A B">
当属性的值包含空格等特殊字符时,需要用双引号括起来。
按属性查找还可以使用前缀查找或者后缀查找:
varicons = $(
'[name^=icon]');
// 找出所有name属性值以icon开头的DOM// 例如: name="icon-1", name="icon-2"varnames = $(
'[name$=with]');
// 找出所有name属性值以with结尾的DOM// 例如: name="startswith", name="endswith"这个方法尤其适合通过class属性查找,且不受class包含多个名称的影响:
varicons = $(
'[class^="icon-"]');
// 找出所有class包含至少一个以`icon-`开头的DOM// 例如: class="icon-clock", class="abc icon-home"组合查找
组合查找就是把上述简单选择器组合起来使用。如果我们查找
$('[name=email]')
,很可能把表单外的
也找出来,但我们只希望查找,就可以这么写:
var emailInput = $('input[name=email]'); //
不会找出
name="email">同样的,根据tag和class来组合查找也很常见:
var tr = $('tr.red'); //
找出
class="red ..."> ...
多项选择器
多项选择器就是把多个选择器用
,
组合起来一块选:$('p,div'); //
把
和
都选出来
$('p.red,p.green'); //
把
class="red">
和
class="green">
都选出来
要注意的是,选出来的元素是按照它们在HTML中出现的顺序排列的,而且不会有重复元素。例如,
不会被上面的
$('p.red,p.green')
选择两次。练习
使用jQuery选择器分别选出指定元素:
仅选择JavaScript
仅选择Erlang
选择JavaScript和Erlang
选择所有编程语言
选择名字input
选择邮件和名字input
id="para-1" class="color-red">
JavaScript
id="para-2" class="color-green">
Haskell
class="color-red color-green">
Erlang
name="name" class="color-black">
Python
注册新用户
名字:
name="name">
邮件:
name="email">
口令:
name="password" type="password">
层级选择器(Descendant Selector)
如果两个DOM元素具有层级关系,就可以用
$('ancestor descendant')
来选择,层级之间用空格隔开。例如:
class="lang">
class="lang-javascript"> JavaScript
class="lang-python"> Python
class="lang-lua"> Lua
要选出JavaScript,可以用层级选择器:
$('ul.lang li.lang-javascript'); // [
class="lang-javascript"> JavaScript
]
$('div.testing li.lang-javascript'); // [
class="lang-javascript"> JavaScript
]
因为
和都是
的祖先节点,所以上面两种方式都可以选出相应的
节点。
要选择所有的
节点,用:
$('ul.lang li');
这种层级选择器相比单个的选择器好处在于,它缩小了选择范围,因为首先要定位父节点,才能选择相应的子节点,这样避免了页面其他不相关的元素。
例如:
$('form[name=up
load] input');就把选择范围限定在
name
属性为upload
的表单里。如果页面有很多表单,其他表单的不会被选择。
多层选择也是允许的:
$('form.test p input'); //
在form表单选择被
包含的
子选择器(Child Selector)
子选择器
$('parent>child')
类似层级选择器,但是限定了层级关系必须是父子关系,就是节点必须是
节点的直属子节点。还是以上面的例子:
$('ul.lang>li.lang-javascript'); //
可以选出[
class="lang-javascript"> JavaScript
]
$('div.testing>li.lang-javascript'); // [],
无法选出,因为
和
不构成父子关系
过滤器(Filter)
过滤器一般不单独使用,它通常附加在选择器上,帮助我们更精确地定位元素。观察过滤器的效果:
$('ul.lang li');
//
选出
JavaScript、
Python和
Lua3
个节点
$('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还有一组特殊的选择器:
:input
:可以选择,
,
和
;
:file
:可以选择,和
input[type=file]
一样;
:checkbox
:可以选择复选框,和input[type=checkbox]
一样;
:radio
:可以选择单选框,和input[type=radio]
一样;
:focus
:可以选择当前输入焦点的元素,例如把光标放到一个上,用
$('input:focus')
就可以选出;
:checked
:选择当前勾上的单选框和复选框,用这个选择器可以立刻获得用户选择的项目,如$('input[type=radio]:checked')
;
:enabled
:可以选择可以正常输入的、
等,也就是没有灰掉的输入;
:disabled
:和:enabled
正好相反,选择那些不能输入的。
此外,jQuery还有很多有用的选择器,例如,选出可见的或隐藏的元素:
$('div:visible');
//
所有可见的div
$('div:hidden');
//
所有隐藏的div
练习
针对如下HTML结构:
class="test-lang">
class="lang-javascript"> JavaScript
class="lang-python"> Python
class="lang-lua"> Lua
class="test-lang">
class="lang-swift"> Swift
class="lang-java"> Java
class="lang-c"> C
查找
通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以这个对象为基准,进行查找和过滤。
最常见的查找是在某个节点的所有子节点中查找,使用
find()
方法,它本身又接收一个任意的选择器。例如如下的HTML结构:
class="js dy"> JavaScript
class="dy"> Python
id="swift"> Swift
class="dy"> Scheme
name="haskell"> Haskell
用
find()
查找:varul = $(
'ul.lang');
// 获得var
dy = ul.find(
'.dy');
// 获得JavaScript, Python, Schemevarswf = ul.find(
'#swift');
// 获得Swiftvarhsk = ul.find(
'[name=haskell]');
// 获得Haskell如果要从当前节点开始向上查找,使用
parent()
方法:varswf = $(
'#swift');
// 获得Swiftvarparent
= swf.
parent();
// 获得Swift的上层节点var
a = swf.
parent(
'.red');
// 获得Swift的上层节点,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象
对于位于同一层级的节点,可以通过
next()
和prev()
方法,例如:当我们已经拿到
Swift
节点后:var swift =
$('#swift');
swift.
next();
//Scheme
swift.
next(
'[name=haskell]');
//
空的jQuery对象,因为
Swift的下一个元素
Scheme不符合条件[name=haskell]
swift.prev();
//Python
swift.prev(
'.dy');
//Python
,因为
Python同时符合过滤器条件.dy
DOM操作
通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以以这个对象为基准,进行查找和过滤。
最常见的查找是在某个节点的所有子节点中查找,使用
find()
方法,它本身又接收一个任意的选择器。例如如下的HTML结构:
- JavaScript
- Python
- Swift
- Scheme
- Haskell
class="js dy"> JavaScript
class="dy"> Python
id="swift"> Swift
class="dy"> Scheme
name="haskell"> Haskell
用
find()
查找:varul = $(
'ul.lang');
// 获得var
dy = ul.find(
'.dy');
// 获得JavaScript, Python, Schemevarswf = ul.find(
'#swift');
// 获得Swiftvarhsk = ul.find(
'[name=haskell]');
// 获得Haskell如果要从当前节点开始向上查找,使用
parent()
方法:varswf = $(
'#swift');
// 获得Swiftvarparent
= swf.
parent();
// 获得Swift的上层节点var
a = swf.
parent(
'.red');
// 获得Swift的上层节点,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象
对于位于同一层级的节点,可以通过
next()
和prev()
方法,例如:当我们已经拿到
Swift
节点后: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()
方法可以过滤掉不符合选择器条件的节点:varlangs = $(
'ul.lang li');
// 拿到JavaScript, Python, Swift, Scheme和Haskellvara = langs.filter(
'.dy');
// 拿到JavaScript, Python, Scheme或者传入一个函数,要特别注意函数内部的
this
被绑定为DOM对象,不是jQuery对象:varlangs = $(
'ul.lang li');
// 拿到JavaScript, Python, Swift, Scheme和Haskelllangs.filter(
function () {return
this
.innerHTML.indexOf(
'S') ===
0;
// 返回S开头的节点});
// 拿到Swift, Scheme
map()
方法把一个jQuery对象包含的若干DOM节点转化为其他对象:varlangs = $(
'ul.lang li');
// 拿到JavaScript, Python, Swift, Scheme和Haskellvararr = langs.map(
function () {return
this
.innerHTML;
}).get();
// 用get()拿到包含string的Array:['JavaScript', 'Python', 'Swift', 'Scheme', 'Haskell']此外,一个jQuery对象如果包含了不止一个DOM节点,
first()
、last()
和slice()
方法可以返回一个新的jQuery对象,把不需要的DOM节点去掉:varlangs = $(
'ul.lang li');
// 拿到JavaScript, Python, Swift, Scheme和Haskellvarjs = langs.first();
// JavaScript,相当于$('ul.lang li:first-child')varhaskell = langs.last();
// Haskell, 相当于$('ul.lang li:last-child')varsub = langs.slice(
2,
4);
// Swift, Scheme, 参数和数组的slice()方法一致练习
对于下面的表单:
Name:
name="name">
Email:
name="email">
Password:
name="password" type="password">
Gender:
City:
输入值后,用jQuery获取表单的JSON字符串,key和value分别对应每个输入的name和相应的value,例如:
{"name":"Michael","email":...}
添加DOM
要添加新的DOM节点,除了通过jQuery的
html()
这种暴力方法外,还可以用append()
方法,例如:
JavaScript
Python
Swift
如何向列表新增一个语言?首先要拿到
节点:
var ul =
$('#test-div>ul');
然后,调用
append()
传入HTML片段:ul.append('
Haskell
');
除了接受字符串,
append()
还可以传入原始的DOM对象,jQuery对象和函数对象://
创建DOM对象:
var ps = document.createElement('li');
ps.innerHTML = '
Pascal
';
//
添加DOM对象:
ul.append(ps);
//
添加jQuery对象:
ul.append($('#scheme'));
//
添加函数对象:
ul.append(function (index, html) {
return '
Language - ' + index + '
';
});
传入函数时,要求返回一个字符串、DOM对象或者jQuery对象。因为jQuery的
append()
可能作用于一组DOM节点,只有传入函数才能针对每个DOM生成不同的子节点。
append()
把DOM添加到最后,prepend()
则把DOM添加到最前。另外注意,如果要添加的DOM节点已经存在于HTML文档中,它会首先从文档移除,然后再添加,也就是说,用
append()
,你可以移动一个DOM节点。如果要把新节点插入到指定位置,例如,JavaScript和Python之间,那么,可以先定位到JavaScript,然后用
after()
方法:var js = $('#test-div>ul>li:first-child');
js.after('
Lua
');
也就是说,同级节点可以用
after()
或者before()
方法。
删除节点
要删除DOM节点,拿到jQuery对象后直接调用
remove()
方法就可以了。如果jQuery对象包含若干DOM节点,实际上可以一次删除多个DOM节点:var li = $('#test-div>ul>li');
li.remove(); //
所有
全被删除
练习
除了列出的3种语言外,请再添加Pascal、Lua和Ruby,然后按字母顺序排序节点:
JavaScript
Python
Swift
- 事件
因为JavaScript在浏览器中以单线程模式运行,页面加载后,一旦页面上所有的JavaScript代码被执行完后,就只能依赖触发事件来执行JavaScript代码。
浏览器在接收到用户的鼠标或键盘输入后,会自动在对应的DOM节点上触发相应的事件。如果该节点已经绑定了对应的JavaScript处理函数,该函数就会自动调用。
由于不同的浏览器绑定事件的代码都不太一样,所以用jQuery来写代码,就屏蔽了不同浏览器的差异,我们总是编写相同的代码。
举个例子,假设要在用户点击了超链接时弹出提示框,我们用jQuery这样绑定一个
click
事件:/* HTML:
*
*
id="test-link" href="#0">点我试试
*
*/
//
获取超链接的jQuery对象:
var a = $('#test-link');
a.on('click', function () {
alert('Hello!');
});
实测:点我试试
on
方法用来绑定一个事件,我们需要传入事件名称和对应的处理函数。另一种更简化的写法是直接调用
click()
方法:a.click(
function () {alert(
'Hello!');
});
两者完全等价。我们通常用后面的写法。
jQuery能够绑定的事件主要包括:
鼠标事件
click: 鼠标单击时触发; dblclick:鼠标双击时触发; mouseenter:鼠标进入时触发; mouseleave:鼠标移出时触发; mousemove:鼠标在DOM内部移动时触发; hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave。
键盘事件
键盘事件仅作用在当前焦点的DOM上,通常是
和
。
keydown:键盘按下时触发; keyup:键盘松开时触发; keypress:按一次键后触发。
其他事件
focus:当DOM获得焦点时触发; blur:当DOM失去焦点时触发; change:当
、
或
的内容改变时触发; submit:当
提交时触发; ready:当页面被载入并且DOM树完成初始化后触发。
其中,
ready
仅作用于document
对象。由于ready
事件在DOM完成初始化后触发,且只触发一次,所以非常适合用来写其他的初始化代码。假设我们想给一个表单绑定
submit
事件,下面的代码没有预期的效果:
// 代码有误:
$('#testForm).on('submit', function () {
alert('submit!');
});
...
因为JavaScript在此执行的时候,
尚未载入浏览器,所以
$('#testForm)
返回[]
,并没有绑定事件到任何DOM上。所以我们自己的初始化代码必须放到
document
对象的ready
事件中,保证DOM已完成初始化:
$(document).on('ready', function () {
$('#testForm).on('submit', function () {
alert('submit!');
});
});
...
这样写就没有问题了。因为相关代码会在DOM树初始化后再执行。
由于
ready
事件使用非常普遍,所以可以这样简化:$(document).ready(
function () {// on('submit', function)也可以简化:
$(
'#testForm).submit(function () {alert('submit!
');});
});
甚至还可以再简化为:
$(
function () {// init...
});
上面的这种写法最为常见。如果你遇到
$(function () {...})
的形式,牢记这是document
对象的ready
事件处理函数。完全可以反复绑定事件处理函数,它们会依次执行:
$(
function () {console.log(
'init A...');
});
$(
function () {console.log(
'init B...');
});
$(
function () {console.log(
'init C...');
});
事件参数
有些事件,如
mousemove
和keypress
,我们需要获取鼠标位置和按键的值,否则监听这些事件就没什么意义了。所有事件都会传入Event
对象作为参数,可以从Event
对象上获取到更多的信息:$(
function () {$(
'#testMouseMoveDiv').mousemove(
function (e) {$(
'#testMouseMoveSpan').text(
'pageX = '+ e.pageX +
', pageY = '+ e.pageY);
});
});
效果实测:
mousemove: pageX = 709, pageY = 2955
在此区域移动鼠标试试
取消绑定
一个已被绑定的事件可以解除绑定,通过
off('click', function)
实现:function hello() {
alert(
'hello!');
}
a.click(hello);
// 绑定事件// 10秒钟后解除绑定:
setTimeout(
function () {a.off(
'click', hello);
},
10000);
需要特别注意的是,下面这种写法是无效的:
// 绑定事件:
a.click(
function () {alert(
'hello!');
});
// 解除绑定:
a.off(
'click',
function () {alert(
'hello!');
});
这是因为两个匿名函数虽然长得一模一样,但是它们是两个不同的函数对象,
off('click', function () {...})
无法移除已绑定的第一个匿名函数。为了实现移除效果,可以使用
off('click')
一次性移除已绑定的click
事件的所有处理函数。同理,无参数调用
off()
一次性移除已绑定的所有类型的事件处理函数。
事件触发条件
一个需要注意的问题是,事件的触发总是由用户操作引发的。例如,我们监控文本框的内容改动:
varinput = $(
'#test-input');
input.change(
function () {console.log(
'changed...');
});
当用户在文本框中输入时,就会触发
change
事件。但是,如果用JavaScript代码去改动文本框的值,将不会触发change
事件:var input =
$('#test-input');
input.val(
'change it!');
//
无法触发change事件
有些时候,我们希望用代码触发
change
事件,可以直接调用无参数的change()
方法来触发该事件:var input =
$('#test-input');
input.val(
'change it!');
input.change();
//
触发change事件
input.change()
相当于input.trigger('change')
,它是trigger()
方法的简写。为什么我们希望手动触发一个事件呢?如果不这么做,很多时候,我们就得写两份一模一样的代码。