$(document).ready()是jQuery基於頁面加載執行任務的一種主要方式。但並非惟一,原生的window.onload也可實現相同效果。雖然兩者具備相似效果,但它們在觸發操做的時間上存在微妙差別,這種差別只有在加載的資源多到必定程度時纔會體現出來。當文檔徹底下載到瀏覽器中時,會觸發window.onload。這意味着頁面上的所有元素對JavaScript而言都是可操做的,這種狀況對編寫功能性的代碼很是有利,由於無需考慮加載次序。另外一方面,經過$(document).ready()註冊的事件處理程序,則會在DOM徹底就緒並可以使用時調用。雖然這也意味着全部元素對腳本而言都是能夠訪問的,可是,卻不意味着全部關聯的文件都已下載完畢
爲保證JavaScript代碼執行之前頁面已經應用了樣式,最好是在 <head>元素中把 <link rel="stylesheet"> 標籤和 <style> 標籤放在 <script> 標籤前
通常來講,$(document).ready()要優於使用onload,但必需要明確,由於支持文件可能尚未加載完成,因此相似圖像的高度寬度屬性此時不必定有效。若是須要訪問這些屬性,可能就得選擇實現一個onload(或使用jQuery爲load事件設置處理程序)。這兩種機制和平共存
咱們既能夠在HTML標記中指定該函數:<body onload="doStuff();">也可在JavaScript中指定:window.onload = doStuff;這兩種方式都會在頁面加載完成後執行這個函數。但後者的優勢在於,它能使行爲更清晰地從標記中分離出來。注意,這裏在將函數指定爲處理程序時,省略了(),只用了函數名。若是帶(),函數會被當即調用;沒有,函數名就只是函數的標識符或函數引用,可用於在未來再調用.在只有一個函數的狀況下,這樣作沒問題。但假設又定義了第2個函數:
function doOtherStuff() {
//執行另一種任務......
}
也可將它指定爲基於頁面的加載來運行:window.onload = doOtherStuff;然而,此次指定的函數會取代剛纔指定的第1個函數。由於.onload屬性一次只能保存對一個函數的引用,因此不能在現有行爲基礎上再增長新行爲。經過$(document).ready()機制能很好地解決這個問題。每次調用$(document).ready()都會向內部的行爲隊列中添加一個新函數,當頁面加載完成後,全部函數都會被執行。並且,這些函數會按照註冊它們的順序依次執行(經過window.onload雖然也可註冊多個函數,但卻不能保證按順序執行)。
在某些狀況下,可能有必要在同一個頁面中使用多個JavaScript庫。因爲不少庫都使用$標識符,所以就需一種方式來避免名稱衝突。爲解決這個問題,jQuery提供了一個jQuery.noConflict(),調用該方法能夠把對$標識符的控制權讓渡還給其餘庫:
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script>
jQuery.noConflict();
</script>
<script src="myscript.js"></script>
首先,包含jQuery以外的庫(這裏是Prototype)。而後,包含jQuery庫,取得對$的使用權。接着,調用.noConflict()方法讓出$,以便將控制權交還給Prototype。這樣就可在自定義腳本中使用2個庫——可是,在須要使用jQuery方法時,必須記住要用jQuery而不是$來調用。在這種狀況下,還有一個在.ready()中使用$的技巧。傳遞給它的回調函數能夠接收一個參數——jQuery對象自己。利用這個參數,能夠從新命名jQuery爲$,而沒必要擔憂形成衝突:
jQuery(document).ready(function($) {
//在這裏,能夠正常使用!
});
或者,也可使用剛剛介紹的簡寫語法:
jQuery(function($) {
//使用$的代碼
});
$(document).ready(function() {
$('#switcher-large').on('click', function() {
$('body').addClass('large');
});
});
這裏的所有操做就是綁定一個事件。屢次調用.on()也沒有任何問題,便可按需爲同一事件追加更多行爲。但這不是最優雅或最有效的方式
容許多個元素響應單擊事件的一種策略叫作事件捕獲(事件捕獲和事件冒泡是「瀏覽器大戰」時期分別由Netscape和微軟提出的2種相反的事件傳播模型)。在事件捕獲過程當中,事件首先會交給最外層的元素,接着再交給更具體的元素。另外一種相反的策略叫作事件冒泡。即當事件發生時,會首先發送給最具體的元素,在這個元素得到響應機會以後,事件會向上冒泡到更通常的元素。絕不奇怪,不一樣的瀏覽器開發者最初採用的是不一樣的事件傳播模型。於是,最終出臺的DOM標準規定應該同時使用這2種策略:首先,事件從通常到具體元素逐層捕獲,而後再經過冒泡返回DOM樹的頂層。而事件處理程序可註冊到這個過程當中的任何一個階段。爲確保跨瀏覽器的一致性,也爲了讓人容易理解,jQuery始終會在模型的冒泡階段註冊事件處理程序。所以,咱們老是能夠假定最具體的元素會首先得到響應事件的機會。
事件冒泡可能會致使始料不及的行爲,特別是在錯誤的元素響應mouseover或mouseout事件的狀況下。假設在咱們的例子中,爲<div>添加了一個mouseout事件處理程序。當用戶的鼠標指針退出這個<div>時,會按照預期運行mouseout處理程序。由於這個過程發生在頂層元素上,因此其餘元素不會取得這個事件。可是,當指針從<a>元素上離開時,<a>元素也會取得一個mouseout事件。而後,這個事件會向上冒泡到<span>和<div>,從而觸發上述的事件處理程序。這種冒泡序列極可能不是咱們所但願的。
而mouseenter和mouseleave,不管是單獨綁定,仍是在.hover()方法中組合綁定,均可避免這些冒泡問題。在使用它們處理事件時,不用擔憂某些非目標元素獲得mouseover或mouseout事件致使的問題。jquery
//未完成的代碼
$(document).ready(function() {
$('#switcher').click(function() {
$('#switcher button').toggleClass('hidden');
});
});
這種改變會使樣式轉換器的整個區域均可經過單擊切換其可見性。但同時也形成一個問題,即單擊按鈕會在修改內容區的樣式以後摺疊樣式轉換器。致使這個問題的緣由就是事件冒泡,即事件首先被按鈕處理,而後又沿着DOM樹向上傳遞,直至到達<div id="switcher">激活事件處理程序並隱藏按鈕。要解決這個問題,必須訪問事件對象。事件對象是一種DOM結構,它會在元素得到處理事件的機會時傳遞給被調用的事件處理程序。這個對象中包含着與事件有關的信息(例如事件發生時的鼠標指針位置),也提供了能夠用來影響事件在DOM中傳遞進程的一些方法。爲使用事件對象,需爲函數加1個參數:
$(document).ready(function() {
$('#switcher').click(function(event) {
$('#switcher button').toggleClass('hidden');
});
});
注意,這裏把事件對象命名爲event,主要是爲了讓你們一看就知道是什麼,不是必須這樣命名。event保存事件對象。event.target保存發生事件的目標元素。事件對象的.stopPropagation() (要在IE8及更早版本中安全使用,需將事件對象的cancelBubble屬性設爲false(但若經過jQuery來註冊全部事件處理程序,就可放心使用))可徹底阻止事件冒泡。
在事件的環境中完成了某些驗證以後,一般會用到.preventDefault()。例如,在表單提交期間,對用戶是否填寫了必填字段進行檢查,若是用戶沒有填寫相應字段,就需阻止默認操做
事件傳播和默認操做是相互獨立的2套機制,在2者任何一方發生時,均可終止另外一方。若是想要同時中止事件傳播和默認操做,可在事件處理程序中return false,這是對在事件對象上同時調用.stopPropagation()和.preventDefault()的一種簡寫方式
is()與.hasClass():要測試元素是否包含某個類,可以使用.hasClass()。不過,.is()更靈活,它能夠測試任何選擇符表達式
$('#switcher').on('click', 'button', function() {
var bodyClass = event.target.id.split('-')[1];
$('body').removeClass().addClass(bodyClass);
$('#switcher button').removeClass('selected');
$(this).addClass('selected');
});(內置的事件委託)
$(document).ready(function() {
$('#switcher').click(function(event) {
if (!$(event.target).is('button')) $('#switcher button').toggleClass('hidden');
});
$('#switcher-narrow, #switcher-large').click(function() {
$('#switcher').off('click');
});
});(移除事件處理程序)
$(document).ready(function() {
$('#switcher').on('click.collapse', function(event) {
if (!$(event.target).is('button')) $('#switcher button').toggleClass('hidden');
});
$('#switcher-narrow, #switcher-large').click(function() {
$('#switcher').off('click.collapse');
});
});(用命名空間使.off()更據針對性)對事件處理系統,後綴.collapse不可見
$(document).ready(function() {
var toggleSwitcher = function(event) {
if (!$(event.target).is('button')) $('#switcher button').toggleClass('hidden');
};
$('#switcher').on('click.collapse', toggleSwitcher);
});(事件的從新綁定)使用命名函數時,必須省略函數名後的()。()會致使函數被調用,而非被引用
$(document).ready(function() {
var toggleSwitcher = function(event) {
if (!$(event.target).is('button')) $('#switcher button').toggleClass('hidden');
};
$('#switcher').on('click', toggleSwitcher);
$('#switcher button').click(function() {
$('#switcher').off('click', toggleSwitcher);
if (this.id== 'switcher-default') $('#switcher').on('click', toggleSwitcher);
});
});(完整的事件解除與從新綁定)對於只需觸發一次,隨後當即解綁的也有一種簡寫方法——.one():$('#switcher').one('click', toggleSwitcher);
$(document).ready(function() {
var triggers = {
D: 'default',
N: 'narrow',
L: 'large'
};
$(document).keyup(function(event) {
var key = String.fromCharCode(event.which);
if (key in triggers) $('#switcher-' + triggers[key]).click();
});
});鍵盤事件分2類:直接對鍵盤按鍵給出響應事件(keyup和keydown)和對文本輸入給出響應事件(keypress)。若是想知道用戶按了哪一個鍵,偵聽keyup/keydown;輸入的是什麼字符,偵聽keypress
api