jQuery是目前使用最廣泛的JavaScript函數庫。據[統計](http://w3techs.com/technologies/details/js-jquery/all/all),全世界57.5%的網站使用jQuery,在使用JavaScript函數庫的網站中,93.0%使用jQuery。它已經成了開發者必須學會的技能。
jQuery的最大優勢有兩個。首先,它基本是一個DOM操作工具,可以使操作DOM對象變得異常容易。其次,它統一了不同瀏覽器的API接口,使得代碼在所有現代瀏覽器均能運行,開發者不用擔心瀏覽器之間的差異。
[TOC]
## jQuery的加載
一般采用下面的寫法,在網頁中加載jQuery。
~~~
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery-1.11.0.min.js" type="text/javascript"><\/script>')
</script>
~~~
上面代碼有兩點需要注意。一是采用[CDN](http://jquery.com/download/#using-jquery-with-a-cdn)加載。如果CDN加載失敗,則退回到本地加載。二是采用協議無關的加載網址(使用雙斜線表示),同時支持http協議和https協議。
目前常用的jQuery CDN有以下這些。
* [Google CDN](https://developers.google.com/speed/libraries/devguide#jquery)
* [Microsoft CDN](http://www.asp.net/ajax/cdn#jQuery_Releases_on_the_CDN_0)
* [jQuery CDN](http://jquery.com/download/#jquery-39-s-cdn-provided-by-maxcdn)
* [CDNJS CDN](http://cdnjs.com/libraries/jquery/)
* [jsDelivr CDN](http://www.jsdelivr.com/#!jquery)
上面這段代碼最好放到網頁尾部。如果需要支持IE 6/7/8,就使用jQuery 1.x版,否則使用最新版。
## jQuery基礎
### jQuery對象
jQuery最重要的概念,就是jQuery對象。它是一個全局對象,可以簡寫為美元符號$。也就是說,jQuery和$兩者是等價的。
在網頁中加載jQuery函數庫以后,就可以使用jQuery對象了。jQuery的全部方法,都定義在這個對象上面。
~~~
var listItems = jQuery('li');
// or
var listItems = $('li');
~~~
上面兩行代碼是等價的,表示選中網頁中所有的li元素。
### jQuery構造函數
jQuery對象本質上是一個構造函數,主要作用是返回jQuery對象的實例。比如,上面代碼表面上是選中li元素,實際上是返回對應于li元素的jQuery實例。因為只有這樣,才能在DOM對象上使用jQuery提供的各種方法。
~~~
$('body').nodeType
// undefined
$('body') instanceof jQuery
// true
~~~
上面代碼表示,由于jQuery返回的不是DOM對象,所以沒有DOM屬性nodeType。它返回的是jQuery對象的實例。
(1)CSS選擇器作為參數
jQuery構造函數的參數,主要是CSS選擇器,就像上面的那個例子。下面是另外一些CSS選擇器的例子。
~~~
$("*")
$("#lastname")
$(".intro")
$("h1,div,p")
$("p:last")
$("tr:even")
$("p:first-child")
$("p:nth-of-type(2)")
$("div + p")
$("div:has(p)")
$(":empty")
$("[title^='Tom']")
~~~
本書不講解CSS選擇器,請讀者參考有關書籍和jQuery文檔。
(2)DOM對象作為參數
jQuery構造函數的參數,還可以是DOM對象。它也會被轉為jQuery對象的實例。
~~~
$(document.body) instanceof jQuery
// true
~~~
上面代碼中,jQuery的參數不是CSS選擇器,而是一個DOM對象,返回的依然是jQuery對象的實例。
如果有多個DOM元素要轉為jQuery對象的實例,可以把DOM元素放在一個數組里,輸入jQuery構造函數。
~~~
$([document.body, document.head])
~~~
(3)HTML代碼作為參數
如果直接在jQuery構造函數中輸入HTML代碼,返回的也是jQuery實例。
~~~
$('<li class="greet">test</li>')
~~~
上面代碼從HTML代碼生成了一個jQuery實例,它與從CSS選擇器生成的jQuery實例完全一樣。唯一的區別就是,它對應的DOM結構不屬于當前文檔。
上面代碼也可以寫成下面這樣。
~~~
$( '<li>', {
html: 'test',
'class': 'greet'
});
~~~
上面代碼中,由于class是javaScript的保留字,所以只能放在引號中。
通常來說,上面第二種寫法是更好的寫法。
~~~
$('<input class="form-control" type="hidden" name="foo" value="bar" />')
// 相當于
$('<input/>', {
class: 'form-control',
type: 'hidden',
name: 'foo',
value: 'bar'
})
// 或者
$('<input/>')
.addClass('form-control')
.attr('type', 'hidden')
.attr('name', 'foo')
.val('bar')
~~~
(4)第二個參數
默認情況下,jQuery將文檔的根元素(html)作為尋找匹配對象的起點。如果要指定某個網頁元素(比如某個div元素)作為尋找的起點,可以將它放在jQuery函數的第二個參數。
~~~
$('li', someElement);
~~~
上面代碼表示,只尋找屬于someElement對象下屬的li元素。someElement可以是jQuery對象的實例,也可以是DOM對象。
### jQuery構造函數返回的結果集
jQuery的核心思想是“先選中某些網頁元素,然后對其進行某種處理”(find something, do something),也就是說,先選擇后處理,這是jQuery的基本操作模式。所以,絕大多數jQuery操作都是從選擇器開始的,返回一個選中的結果集。
(1)length屬性
jQuery對象返回的結果集是一個類似數組的對象,包含了所有被選中的網頁元素。查看該對象的length屬性,可以知道到底選中了多少個結果。
~~~
if ( $('li').length === 0 ) {
console.log('不含li元素');
}
~~~
上面代碼表示,如果網頁沒有li元素,則返回對象的length屬性等于0。這就是測試有沒有選中的標準方法。
所以,如果想知道jQuery有沒有選中相應的元素,不能寫成下面這樣。
~~~
if ($('div.foo')) { ... }
~~~
因為不管有沒有選中,jQuery構造函數總是返回一個實例對象,而對象的布爾值永遠是true。使用length屬性才是判斷有沒有選中的正確方法。
~~~
if ($('div.foo').length) { ... }
~~~
(2)下標運算符
jQuery選擇器返回的是一個類似數組的對象。但是,使用下標運算符取出的單個對象,并不是jQuery對象的實例,而是一個DOM對象。
~~~
$('li')[0] instanceof jQuery // false
$('li')[0] instanceof Element // true
~~~
上面代碼表示,下標運算符取出的是Element節點的實例。所以,通常使用下標運算符將jQuery實例轉回DOM對象。
(3)is方法
is方法返回一個布爾值,表示選中的結果是否符合某個條件。這個用來驗證的條件,可以是CSS選擇器,也可以是一個函數,或者DOM元素和jQuery實例。
~~~
$('li').is('li') // true
$('li').is($('.item'))
$('li').is(document.querySelector('li'))
$('li').is(function() {
return $("strong", this).length === 0;
});
~~~
(4)get方法
jQuery實例的get方法是下標運算符的另一種寫法。
~~~
$('li').get(0) instanceof Element // true
~~~
(5)eq方法
如果想要在結果集取出一個jQuery對象的實例,不需要取出DOM對象,則使用eq方法,它的參數是實例在結果集中的位置(從0開始)。
~~~
$('li').eq(0) instanceof jQuery // true
~~~
由于eq方法返回的是jQuery的實例,所以可以在返回結果上使用jQuery實例對象的方法。
(6)each方法,map方法
這兩個方法用于遍歷結果集,對每一個成員進行某種操作。
each方法接受一個函數作為參數,依次處理集合中的每一個元素。
~~~
$('li').each(function( index, element) {
$(element).prepend( '<em>' + index + ': </em>' );
});
// <li>Hello</li>
// <li>World</li>
// 變為
// <li><em>0: </em>Hello</li>
// <li><em>1: </em>World</li>
~~~
從上面代碼可以看出,作為each方法參數的函數,本身有兩個參數,第一個是當前元素在集合中的位置,第二個是當前元素對應的DOM對象。
map方法的用法與each方法完全一樣,區別在于each方法沒有返回值,只是對每一個元素執行某種操作,而map方法返回一個新的jQuery對象。
~~~
$("input").map(function (index, element){
return $(this).val();
})
.get()
.join(", ")
~~~
上面代碼表示,將所有input元素依次取出值,然后通過get方法得到一個包含這些值的數組,最后通過數組的join方法返回一個逗號分割的字符串。
(8)內置循環
jQuery默認對當前結果集進行循環處理,所以如果直接使用jQuery內置的某種方法,each和map方法是不必要的。
~~~
$(".class").addClass("highlight");
~~~
上面代碼會執行一個內部循環,對每一個選中的元素進行addClass操作。由于這個原因,對上面操作加上each方法是不必要的。
~~~
$(".class").each(function(index,element){
$(element).addClass("highlight");
});
// 或者
$(".class").each(function(){
$(this).addClass("highlight");
});
~~~
上面代碼的each方法,都是沒必要使用的。
由于內置循環的存在,從性能考慮,應該盡量減少不必要的操作步驟。
~~~
$(".class").css("color", "green").css("font-size", "16px");
// 應該寫成
$(".class").css({
"color": "green",
"font-size": "16px"
});
~~~
### 鏈式操作
jQuery最方便的一點就是,它的大部分方法返回的都是jQuery對象,因此可以鏈式操作。也就是說,后一個方法可以緊跟著寫在前一個方法后面。
~~~
$('li').click(function (){
$(this).addClass('clicked');
})
.find('span')
.attr( 'title', 'Hover over me' );
~~~
### $(document).ready()
$(document).ready方法接受一個函數作為參數,將該參數作為document對象的DOMContentLoaded事件的回調函數。也就是說,當頁面解析完成(即下載完標簽)以后,在所有外部資源(圖片、腳本等)完成加載之前,該函數就會立刻運行。
~~~
$( document ).ready(function() {
console.log( 'ready!' );
});
~~~
上面代碼表示,一旦頁面完成解析,就會運行ready方法指定的函數,在控制臺顯示“ready!”。
該方法通常作為網頁初始化手段使用,jQuery提供了一種簡寫法,就是直接把回調函數放在jQuery對象中。
~~~
$(function() {
console.log( 'ready!' );
});
~~~
上面代碼與前一段代碼是等價的。
### $.noConflict方法
jQuery使用美元符號($)指代jQuery對象。某些情況下,其他函數庫也會用到美元符號,為了避免沖突,$.noConflict方法允許將美元符號與jQuery脫鉤。
~~~
<script src="other_lib.js"></script>
<script src="jquery.js"></script>
<script>$.noConflict();</script>
~~~
上面代碼就是$.noConflict方法的一般用法。在加載jQuery之后,立即調用該方法,會使得美元符號還給前面一個函數庫。這意味著,其后再調用jQuery,只能寫成jQuery.methond的形式,而不能用$.method了。
為了避免沖突,可以考慮從一開始就只使用jQuery代替美元符號。
## jQuery實例對象的方法
除了上一節提到的is、get、eq方法,jQuery實例還有許多其他方法。
### 結果集的過濾方法
選擇器選出一組符合條件的網頁元素以后,jQuery提供了許多方法,可以過濾結果集,返回更準確的目標。
(1)first方法,last方法
first方法返回結果集的第一個成員,last方法返回結果集的最后一個成員。
~~~
$("li").first()
$("li").last()
~~~
(2)next方法,prev方法
next方法返回緊鄰的下一個同級元素,prev方法返回緊鄰的上一個同級元素。
~~~
$("li").first().next()
$("li").last().prev()
$("li").first().next('.item')
$("li").last().prev('.item')
~~~
如果next方法和prev方法帶有參數,表示選擇符合該參數的同級元素。
(3)parent方法,parents方法,children方法
parent方法返回當前元素的父元素,parents方法返回當前元素的所有上級元素(直到html元素)。
~~~
$("p").parent()
$("p").parent(".selected")
$("p").parents()
$("p").parents("div")
~~~
children方法返回選中元素的所有子元素。
~~~
$("div").children()
$("div").children(".selected")
// 下面的寫法結果相同,但是效率較低
$('div > *')
$('div > .selected')
~~~
上面這三個方法都接受一個選擇器作為參數。
(4)siblings方法,nextAll方法,prevAll方法
siblings方法返回當前元素的所有同級元素。
~~~
$('li').first().siblings()
$('li').first().siblings('.item')
~~~
nextAll方法返回當前元素其后的所有同級元素,prevAll方法返回當前元素前面的所有同級元素。
~~~
$('li').first().nextAll()
$('li').last().prevAll()
~~~
(5)closest方法,find方法
closest方法返回當前元素,以及當前元素的所有上級元素之中,第一個符合條件的元素。find方法返回當前元素的所有符合條件的下級元素。
~~~
$('li').closest('div')
$('div').find('li')
~~~
上面代碼中的find方法,選中所有div元素下面的li元素,等同于$('li', 'div')。由于這樣寫縮小了搜索范圍,所以要優于$('div li')的寫法。
(6)find方法,add方法,addBack方法,end方法
add方法用于為結果集添加元素。
~~~
$('li').add('p')
~~~
addBack方法將當前元素加回原始的結果集。
~~~
$('li').parent().addBack()
~~~
end方法用于返回原始的結果集。
~~~
$('li').first().end()
~~~
(7)filter方法,not方法,has方法
filter方法用于過濾結果集,它可以接受多種類型的參數,只返回與參數一致的結果。
~~~
// 返回符合CSS選擇器的結果
$('li').filter('.item')
// 返回函數返回值為true的結果
$("li").filter(function(index) {
return index % 2 === 1;
})
// 返回符合特定DOM對象的結果
$("li").filter(document.getElementById("unique"))
// 返回符合特定jQuery實例的結果
$("li").filter($("#unique"))
~~~
not方法的用法與filter方法完全一致,但是返回相反的結果,即過濾掉匹配項。
~~~
$('li').not('.item')
~~~
has方法與filter方法作用相同,但是只過濾出子元素符合條件的元素。
~~~
$("li").has("ul")
~~~
上面代碼返回具有ul子元素的li元素。
### DOM相關方法
許多方法可以對DOM元素進行處理。
(1)html方法和text方法
html方法返回該元素包含的HTML代碼,text方法返回該元素包含的文本。
假定網頁只含有一個p元素。
~~~
<p><em>Hello World!</em></p>
~~~
html方法和text方法的返回結果分別如下。
~~~
$('p').html()
// <em>Hello World!</em>
$('p').text()
// Hello World!
~~~
jQuery的許多方法都是取值器(getter)與賦值器(setter)的合一,即取值和賦值都是同一個方法,不使用參數的時候為取值器,使用參數的時候為賦值器。
上面代碼的html方法和text方法都沒有參數,就會當作取值器使用,取回結果集的第一個元素所包含的內容。如果對這兩個方法提供參數,就是當作賦值器使用,修改結果集所有成員的內容,并返回原來的結果集,以便進行鏈式操作。
~~~
$('p').html('<strong>你好</strong>')
// 網頁代碼變為<p><strong>你好</strong></p>
$('p').text('你好')
// 網頁代碼變為<p>你好</p>
~~~
下面要講到的jQuery其他許多方法,都采用這種同一個方法既是取值器又是賦值器的模式。
html方法和text方法還可以接受一個函數作為參數,函數的返回值就是網頁元素所要包含的新的代碼和文本。這個函數接受兩個參數,第一個是網頁元素在集合中的位置,第二個參數是網頁元素原來的代碼或文本。
~~~
$('li').html(function (i, v){
return (i + ': ' + v);
})
// <li>Hello</li>
// <li>World</li>
// 變為
// <li>0: Hello</li>
// <li>1: World</li>
~~~
(2)addClass方法,removeClass方法,toggleClass方法
addClass方法用于添加一個類,removeClass方法用于移除一個類,toggleClass方法用于折疊一個類(如果無就添加,如果有就移除)。
~~~
$('li').addClass('special')
$('li').removeClass('special')
$('li').toggleClass('special')
~~~
(3)css方法
css方法用于改變CSS設置。
該方法可以作為取值器使用。
~~~
$('h1').css('fontSize');
~~~
css方法的參數是css屬性名。這里需要注意,CSS屬性名的CSS寫法和DOM寫法,兩者都可以接受,比如font-size和fontSize都行。
css方法也可以作為賦值器使用。
~~~
$('li').css('padding-left', '20px')
// 或者
$('li').css({
'padding-left': '20px'
});
~~~
上面兩種形式都可以用于賦值,jQuery賦值器基本上都是如此。
(4)val方法
val方法返回結果集第一個元素的值,或者設置當前結果集所有元素的值。
~~~
$('input[type="text"]').val()
$('input[type="text"]').val('new value')
~~~
(5)prop方法,attr方法
首先,這里要區分兩種屬性。
一種是網頁元素的屬性,比如a元素的href屬性、img元素的src屬性。這要使用attr方法讀寫。
~~~
// 讀取屬性值
$('textarea').attr(name)
//寫入屬性值
$('textarea').attr(name, val)
~~~
另一種是DOM元素的屬性,比如tagName、nodeName、nodeType等等。這要使用prop方法讀寫。
~~~
// 讀取屬性值
$('textarea').prop(name)
// 寫入屬性值
$('textarea').prop(name, val)
~~~
所以,attr方法和prop方法針對的是不同的屬性。在英語中,attr是attribute的縮寫,prop是property的縮寫,中文很難表達出這種差異。有時,attr方法和prop方法對同一個屬性會讀到不一樣的值。比如,網頁上有一個單選框。
~~~
<input type="checkbox" checked="checked" />
~~~
對于checked屬性,attr方法讀到的是checked,prop方法讀到的是true。
~~~
$(input[type=checkbox]).attr("checked") // "checked"
$(input[type=checkbox]).prop("checked") // true
~~~
可以看到,attr方法讀取的是網頁上該屬性的值,而prop方法讀取的是DOM元素的該屬性的值,根據規范,element.checked應該返回一個布爾值。所以,判斷單選框是否選中,要使用prop方法。事實上,不管這個單選框是否選中,attr("checked")的返回值都是checked。
~~~
if ($(elem).prop("checked")) { /*... */ };
// 下面兩種方法亦可
if ( elem.checked ) { /*...*/ };
if ( $(elem).is(":checked") ) { /*...*/ };
~~~
(6)removeProp方法,removeAttr方法
removeProp方法移除某個DOM屬性,removeAttr方法移除某個HTML屬性。
~~~
$("a").prop("oldValue",1234).removeProp('oldValue')
$('a').removeAttr("title")
~~~
(7)data方法
data方法用于在一個DOM對象上儲存數據。
~~~
// 儲存數據
$("body").data("foo", 52);
// 讀取數據
$("body").data("foo");
~~~
該方法可以在DOM節點上儲存各種類型的數據。
### 添加、復制和移動網頁元素的方法
jQuery方法提供一系列方法,可以改變元素在文檔中的位置。
(1)append方法,appendTo方法
append方法將參數中的元素插入當前元素的尾部。
~~~
$("div").append("<p>World</p>")
// <div>Hello </div>
// 變為
// <div>Hello <p>World</p></div>
~~~
appendTo方法將當前元素插入參數中的元素尾部。
~~~
$("<p>World</p>").appendTo("div")
~~~
上面代碼返回與前一個例子一樣的結果。
(2)prepend方法,prependTo方法
prepend方法將參數中的元素,變為當前元素的第一個子元素。
~~~
$("p").prepend("Hello ")
// <p>World</p>
// 變為
// <p>Hello World</p>
~~~
如果prepend方法的參數不是新生成的元素,而是當前頁面已存在的元素,則會產生移動元素的效果。
~~~
$("p").prepend("strong")
// <strong>Hello </strong><p>World</p>
// 變為
// <p><strong>Hello </strong>World</p>
~~~
上面代碼運行后,strong元素的位置將發生移動,而不是克隆一個新的strong元素。不過,如果當前結果集包含多個元素,則除了第一個以后,后面的p元素都將插入一個克隆的strong子元素。
prependTo方法將當前元素變為參數中的元素的第一個子元素。
~~~
$("<p></p>").prependTo("div")
// <div></div>
// 變為
// <div><p></p></div>
~~~
(3)after方法,insertAfter方法
after方法將參數中的元素插在當前元素后面。
~~~
$("div").after("<p></p>")
// <div></div>
// 變為
// <div></div><p></p>
~~~
insertAfter方法將當前元素插在參數中的元素后面。
~~~
$("<p></p>").insertAfter("div")
~~~
上面代碼返回與前一個例子一樣的結果。
(4)before方法,insertBefore方法
before方法將參數中的元素插在當前元素的前面。
~~~
$("div").before("<p></p>")
// <div></div>
// 變為
// <p></p><div></div>
~~~
insertBefore方法將當前元素插在參數中的元素的前面。
~~~
$("<p></p>").insertBefore("div")
~~~
上面代碼返回與前一個例子一樣的結果。
(5)wrap方法,wrapAll方法,unwrap方法,wrapInner方法
wrap方法將參數中的元素變成當前元素的父元素。
~~~
$("p").wrap("<div></div>")
// <p></p>
// 變為
// <div><p></p></div>
~~~
wrap方法的參數還可以是一個函數。
~~~
$("p").wrap(function() {
return "<div></div>";
})
~~~
上面代碼返回與前一個例子一樣的結果。
wrapAll方法為結果集的所有元素,添加一個共同的父元素。
~~~
$("p").wrapAll("<div></div>")
// <p></p><p></p>
// 變為
// <div><p></p><p></p></div>
~~~
unwrap方法移除當前元素的父元素。
~~~
$("p").unwrap()
// <div><p></p></div>
// 變為
// <p></p>
~~~
wrapInner方法為當前元素的所有子元素,添加一個父元素。
~~~
$("p").wrapInner('<strong></strong>')
// <p>Hello</p>
// 變為
// <p><strong>Hello</strong></p>
~~~
(6)clone方法
clone方法克隆當前元素。
~~~
var clones = $('li').clone();
~~~
對于那些有id屬性的節點,clone方法會連id屬性一起克隆。所以,要把克隆的節點插入文檔的時候,務必要修改或移除id屬性。
(7)remove方法,detach方法,replaceWith方法
remove方法移除并返回一個元素,取消該元素上所有事件的綁定。detach方法也是移除并返回一個元素,但是不取消該元素上所有事件的綁定。
~~~
$('p').remove()
$('p').detach()
~~~
replaceWith方法用參數中的元素,替換并返回當前元素,取消當前元素的所有事件的綁定。
~~~
$('p').replaceWith('<div></div>')
~~~
### 動畫效果方法
jQuery提供一些方法,可以很容易地顯示網頁動畫效果。但是,總體上來說,它們不如CSS動畫強大和節省資源,所以應該優先考慮使用CSS動畫。
如果將jQuery.fx.off設為true,就可以將所有動畫效果關閉,使得網頁元素的各種變化一步到位,沒有中間過渡的動畫效果。
(1)動畫效果的簡便方法
jQuery提供以下一些動畫效果方法。
* show:顯示當前元素。
* hide:隱藏當前元素。
* toggle:顯示或隱藏當前元素。
* fadeIn:將當前元素的不透明度(opacity)逐步提升到100%。
* fadeOut:將當前元素的不透明度逐步降為0%。
* slideDown:以從上向下滑入的方式顯示當前元素。
* slideUp:以從下向上滑出的方式隱藏當前元素。
* slideToggle:以垂直滑入或滑出的方式,折疊顯示當前元素。
上面這些方法可以不帶參數調用,也可以接受毫秒或預定義的關鍵字作為參數。
~~~
$('.hidden').show();
$('.hidden').show(300);
$('.hidden').show('slow');
~~~
上面三行代碼分別表示,以默認速度、300毫秒、較慢的速度隱藏一個元素。
jQuery預定義的關鍵字是在jQuery.fx.speeds對象上面,可以自行改動這些值,或者創造新的值。
~~~
jQuery.fx.speeds.fast = 50;
jQuery.fx.speeds.slow = 3000;
jQuery.fx.speeds.normal = 1000;
~~~
上面三行代碼重新定義fast和slow關鍵字對應的毫秒數,并且自定義了normal關鍵字,表示動畫持續時間為1500毫秒。
你可以定義自己的關鍵字。
~~~
jQuery.fx.speeds.blazing = 30;
// 調用
$('.hidden').show('blazing');
~~~
這些方法還可以接受一個函數,作為第二個參數,表示動畫結束后的回調函數。
~~~
$('p').fadeOut(300, function() {
$(this).remove();
});
~~~
上面代碼表示,p元素以300毫秒的速度淡出,然后調用回調函數,將其從DOM中移除。
(2)animate方法
上面這些動畫效果方法,實際上都是animate方法的簡便寫法。在幕后,jQuery都是統一使用animate方法生成各種動畫效果。
animate方法接受三個參數。
~~~
$('div').animate({
left: '+=50', // 增加50
opacity: 0.25,
fontSize: '12px'
},
300, // 持續事件
function() { // 回調函數
console.log('done!');
}
);
~~~
上面代碼表示,animate方法的第一個參數是一個對象,表示動畫結束時相關CSS屬性的值,第二個參數是動畫持續的毫秒數,第三個參數是動畫結束時的回調函數。需要注意的是,第一個參數對象的成員名稱,必須與CSS屬性名稱一致,如果CSS屬性名稱帶有連字號,則需要用“駱駝拼寫法”改寫。
(3)stop方法,delay方法
stop方法表示立即停止執行當前的動畫。
~~~
$("#stop").click(function() {
$(".block").stop();
});
~~~
上面代碼表示,點擊按鈕后,block元素的動畫效果停止。
delay方法接受一個時間參數,表示暫停多少毫秒后繼續執行。
~~~
$("#foo").slideUp(300).delay(800).fadeIn(400)
~~~
上面代碼表示,slideUp動畫之后,暫停800毫秒,然后繼續執行fadeIn動畫。
### 其他方法
jQuery還提供一些供特定元素使用的方法。
serialize方法用于將表單元素的值,轉為url使用的查詢字符串。
~~~
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
console.log( $( this ).serialize() );
});
// single=Single&multiple=Multiple&check=check2&radio=radio1
~~~
serializeArray方法用于將表單元素的值轉為數組。
~~~
$("form").submit(function (event){
console.log($(this).serializeArray());
event.preventDefault();
});
// [
// {name : 'field1', value : 123},
// {name : 'field2', value : 'hello world'}
// ]
~~~
## 事件處理
### 事件綁定的簡便方法
jQuery提供一系列方法,允許直接為常見事件綁定回調函數。比如,click方法可以為一個元素綁定click事件的回調函數。
~~~
$('li').click(function (e){
console.log($(this).text());
});
~~~
上面代碼為li元素綁定click事件的回調函數,點擊后在控制臺顯示li元素包含的文本。
這樣綁定事件的簡便方法有如下一些:
* click
* keydown
* keypress
* keyup
* mouseover
* mouseout
* mouseenter
* mouseleave
* scroll
* focus
* blur
* resize
* hover
如果不帶參數調用這些方法,就是觸發相應的事件,從而引發回調函數的運行。
~~~
$('li').click()
~~~
上面代碼將觸發click事件的回調函數。
需要注意的是,通過這種方法觸發回調函數,將不會引發瀏覽器對該事件的默認行為。比如,對a元素調用click方法,將只觸發事先綁定的回調函數,而不會導致瀏覽器將頁面導向href屬性指定的網址。
下面是一個捕捉用戶按下escape鍵的函數。
~~~
$(document).keyup(function(e) {
if (e.keyCode == 27) {
$('body').toggleClass('show-nav');
// $('body').removeClass('show-nav');
}
});
~~~
上面代碼中,用戶按下escape鍵,jQuery就會為body元素添加/去除名為show-nav的class。
hover方法需要特別說明。它接受兩個回調函數作為參數,分別代表mouseenter和mouseleave事件的回調函數。
~~~
$(selector).hover(handlerIn, handlerOut)
// 等同于
$(selector).mouseenter(handlerIn).mouseleave(handlerOut)
~~~
### on方法,trigger方法,off方法
除了簡便方法,jQuery還提供事件處理的通用方法。
(1)on方法
on方法是jQuery事件綁定的統一接口。事件綁定的那些簡便方法,其實都是on方法的簡寫形式。
on方法接受兩個參數,第一個是事件名稱,第二個是回調函數。
~~~
$('li').on('click', function (e){
console.log($(this).text());
});
~~~
上面代碼為li元素綁定click事件的回調函數。
> 注意,在回調函數內部,this關鍵字指的是發生該事件的DOM對象。為了使用jQuery提供的方法,必須將DOM對象轉為jQuery對象,因此寫成$(this)。
on方法允許一次為多個事件指定同樣的回調函數。
~~~
$('input[type="text"]').on('focus blur', function (){
console.log('focus or blur');
});
~~~
上面代碼為文本框的focus和blur事件綁定同一個回調函數。
on方法還可以為當前元素的某一個子元素,添加回調函數。
~~~
$('ul').on('click', 'li', function (e){
console.log(this);
});
~~~
上面代碼為ul的子元素li綁定click事件的回調函數。采用這種寫法時,on方法接受三個參數,子元素選擇器作為第二個參數,夾在事件名稱和回調函數之間。
這種寫法有兩個好處。首先,click事件還是在ul元素上觸發回調函數,但是會檢查event對象的target屬性是否為li子元素,如果為true,再調用回調函數。這樣就比為li元素一一綁定回調函數,節省了內存空間。其次,這種綁定的回調函數,對于在綁定后生成的li元素依然有效。
on方法還允許向回調函數傳入數據。
~~~
$("ul" ).on("click", {name: "張三"}, function (event){
console.log(event.data.name);
});
~~~
上面代碼在發生click事件之后,會通過event對象的data屬性,在控制臺打印出所傳入的數據(即“張三”)。
(2)trigger方法
trigger方法用于觸發回調函數,它的參數就是事件的名稱。
~~~
$('li').trigger('click')
~~~
上面代碼觸發li元素的click事件回調函數。與那些簡便方法一樣,trigger方法只觸發回調函數,而不會引發瀏覽器的默認行為。
(3)off方法
off方法用于移除事件的回調函數。
~~~
$('li').off('click')
~~~
上面代碼移除li元素所有的click事件回調函數。
(4)事件的名稱空間
同一個事件有時綁定了多個回調函數,這時如果想移除其中的一個回調函數,可以采用“名稱空間”的方式,即為每一個回調函數指定一個二級事件名,然后再用off方法移除這個二級事件的回調函數。
~~~
$('li').on('click.logging', function (){
console.log('click.logging callback removed');
});
$('li').off('click.logging');
~~~
上面代碼為li元素定義了二級事件click.logging的回調函數,click.logging屬于click名稱空間,當發生click事件時會觸發該回調函數。將click.logging作為off方法的參數,就會移除這個回調函數,但是對其他click事件的回調函數沒有影響。
trigger方法也適用帶名稱空間的事件。
~~~
$('li').trigger('click.logging')
~~~
### event對象
當回調函數被觸發后,它們的參數通常是一個事件對象event。
~~~
$(document).on('click', function (e){
// ...
});
~~~
上面代碼的回調函數的參數e,就代表事件對象event。
event對象有以下屬性:
* type:事件類型,比如click。
* which:觸發該事件的鼠標按鈕或鍵盤的鍵。
* target:事件發生的初始對象。
* data:傳入事件對象的數據。
* pageX:事件發生時,鼠標位置的水平坐標(相對于頁面左上角)。
* pageY:事件發生時,鼠標位置的垂直坐標(相對于頁面左上角)。
event對象有以下方法:
* preventDefault:取消瀏覽器默認行為。
* stopPropagation:阻止事件向上層元素傳播。
### 一次性事件
one方法指定一次性的回調函數,即這個函數只能運行一次。這對提交表單很有用。
~~~
$("#button").one( "click", function() { return false; } );
~~~
one方法本質上是回調函數運行一次,即解除對事件的監聽。
~~~
document.getElementById("#button").addEventListener("click", handler);
function handler(e) {
e.target.removeEventListener(e.type, arguments.callee);
return false;
}
~~~
上面的代碼在點擊一次以后,取消了對click事件的監聽。如果有特殊需要,可以設定點擊2次或3次之后取消監聽,這都是可以的。
## 參考鏈接
* Elijah Manor,?[Do You Know When You Are Looping in jQuery?](http://www.elijahmanor.com/2013/01/yo-dawg-i-herd-you-like-loops-so-jquery.html)
* Craig Buckler,?[How to Create One-Time Events in JavaScript](http://www.sitepoint.com/create-one-time-events-javascript/)
* jQuery Fundamentals,?[jQuery Basics](http://jqfundamentals.com/chapter/jquery-basics)
* jQuery Fundamentals,?[Animating Your Pages with jQuery](http://jqfundamentals.com/chapter/effects)
- 第一章 導論
- 1.1 前言
- 1.2 為什么學習JavaScript?
- 1.3 JavaScript的歷史
- 第二章 基本語法
- 2.1 語法概述
- 2.2 數值
- 2.3 字符串
- 2.4 對象
- 2.5 數組
- 2.6 函數
- 2.7 運算符
- 2.8 數據類型轉換
- 2.9 錯誤處理機制
- 2.10 JavaScript 編程風格
- 第三章 標準庫
- 3.1 Object對象
- 3.2 Array 對象
- 3.3 包裝對象和Boolean對象
- 3.4 Number對象
- 3.5 String對象
- 3.6 Math對象
- 3.7 Date對象
- 3.8 RegExp對象
- 3.9 JSON對象
- 3.10 ArrayBuffer:類型化數組
- 第四章 面向對象編程
- 4.1 概述
- 4.2 封裝
- 4.3 繼承
- 4.4 模塊化編程
- 第五章 DOM
- 5.1 Node節點
- 5.2 document節點
- 5.3 Element對象
- 5.4 Text節點和DocumentFragment節點
- 5.5 Event對象
- 5.6 CSS操作
- 5.7 Mutation Observer
- 第六章 瀏覽器對象
- 6.1 瀏覽器的JavaScript引擎
- 6.2 定時器
- 6.3 window對象
- 6.4 history對象
- 6.5 Ajax
- 6.6 同域限制和window.postMessage方法
- 6.7 Web Storage:瀏覽器端數據儲存機制
- 6.8 IndexedDB:瀏覽器端數據庫
- 6.9 Web Notifications API
- 6.10 Performance API
- 6.11 移動設備API
- 第七章 HTML網頁的API
- 7.1 HTML網頁元素
- 7.2 Canvas API
- 7.3 SVG 圖像
- 7.4 表單
- 7.5 文件和二進制數據的操作
- 7.6 Web Worker
- 7.7 SSE:服務器發送事件
- 7.8 Page Visibility API
- 7.9 Fullscreen API:全屏操作
- 7.10 Web Speech
- 7.11 requestAnimationFrame
- 7.12 WebSocket
- 7.13 WebRTC
- 7.14 Web Components
- 第八章 開發工具
- 8.1 console對象
- 8.2 PhantomJS
- 8.3 Bower:客戶端庫管理工具
- 8.4 Grunt:任務自動管理工具
- 8.5 Gulp:任務自動管理工具
- 8.6 Browserify:瀏覽器加載Node.js模塊
- 8.7 RequireJS和AMD規范
- 8.8 Source Map
- 8.9 JavaScript 程序測試
- 第九章 JavaScript高級語法
- 9.1 Promise對象
- 9.2 有限狀態機
- 9.3 MVC框架與Backbone.js
- 9.4 嚴格模式
- 9.5 ECMAScript 6 介紹
- 附錄
- 10.1 JavaScript API列表
- 草稿一:函數庫
- 11.1 Underscore.js
- 11.2 Modernizr
- 11.3 Datejs
- 11.4 D3.js
- 11.5 設計模式
- 11.6 排序算法
- 草稿二:jQuery
- 12.1 jQuery概述
- 12.2 jQuery工具方法
- 12.3 jQuery插件開發
- 12.4 jQuery.Deferred對象
- 12.5 如何做到 jQuery-free?
- 草稿三:Node.js
- 13.1 Node.js 概述
- 13.2 CommonJS規范
- 13.3 package.json文件
- 13.4 npm模塊管理器
- 13.5 fs 模塊
- 13.6 Path模塊
- 13.7 process對象
- 13.8 Buffer對象
- 13.9 Events模塊
- 13.10 stream接口
- 13.11 Child Process模塊
- 13.12 Http模塊
- 13.13 assert 模塊
- 13.14 Cluster模塊
- 13.15 os模塊
- 13.16 Net模塊和DNS模塊
- 13.17 Express框架
- 13.18 Koa 框架