目錄:
一驶冒、選擇網(wǎng)頁元素
二苟翻、改變結(jié)果集
三、鏈?zhǔn)讲僮?br>
四骗污、元素的操作:取值和賦值
五崇猫、元素的操作:移動(dòng)
六、元素的操作:復(fù)制需忿、刪除和創(chuàng)建
七诅炉、工具方法
八蜡歹、事件操作
九、特殊效果
一涕烧、選擇器選擇網(wǎng)頁元素
$(document) //選擇整個(gè)文檔對(duì)象
$('#myId') //選擇ID為myId的網(wǎng)頁元素 最快的選擇器 ==》id月而、元素標(biāo)簽選擇器
$('div.myClass') // 選擇class為myClass的div元素 較慢的選擇器(在低版本ie中,后續(xù)其實(shí)挺快)
// 最慢的選擇器 ==》偽類選擇器议纯、屬性選擇器
$('input[name=first]') // 選擇name屬性等于first的input元素
$('a:first') //選擇網(wǎng)頁中第一個(gè)a元素
$('tr:odd') //選擇表格的奇數(shù)行 :even 偶數(shù)行
$('#myForm :input') // 選擇表單中的input元素
$('div:visible') //選擇可見的div元素
$('div:gt(2)') // 選擇所有的div元素父款,除了前三個(gè)
$('div:animated') // 選擇當(dāng)前處于動(dòng)畫狀態(tài)的div元素
用選擇器的時(shí)候要選擇最合適的,比如
1.1瞻凤、父子元素選擇
// 給定一個(gè)DOM對(duì)象憨攒,然后從中選擇一個(gè)子元素。jQuery會(huì)自動(dòng)把這條語句轉(zhuǎn)成$.parent.find('child')阀参,這會(huì)導(dǎo)致一定的性能損失肝集。它比最快的形式慢了5%-10%。
$('.child', $parent)
//.find()方法會(huì)調(diào)用瀏覽器的原生方法(getElementById蛛壳,getElementByName杏瞻,getElementByTagName等等),所以速度較快衙荐。最推薦使用
// 而且伐憾,由于$parent往往在前面的操作已經(jīng)生成,jQuery會(huì)進(jìn)行緩存赫模,所以進(jìn)一步加快了執(zhí)行速度树肃。
$parent.find('.child')
// 使用$.sibling()和javascript的nextSibling()方法,一個(gè)個(gè)遍歷節(jié)點(diǎn)瀑罗。它比最快的形式大約慢50%胸嘴。
$parent.children('.child')
// jQuery內(nèi)部使用Sizzle引擎,處理各種選擇器斩祭。Sizzle引擎的選擇順序是從右到左劣像,所以這條語句是先選.child,然后再一個(gè)個(gè)過濾出父元素#parent摧玫,這導(dǎo)致它比最快的形式大約慢70%耳奕。
$('#parent > .child')
// 這條語句與上一條是同樣的情況。但是诬像,上一條只選擇直接的子元素屋群,這一條可以于選擇多級(jí)子元素,所以它的速度更慢坏挠,大概比最快的形式慢了77%芍躏。
$('#parent .child')
// jQuery內(nèi)部會(huì)將這條語句轉(zhuǎn)成$('#parent').find('.child'),比最快的形式慢了23%降狠。
$('.child', $('#parent'))
二对竣、改變結(jié)果集:提供過濾器對(duì)結(jié)果集進(jìn)行篩選
$('div').has('p'); // 選擇包含p元素的div元素
$('div').not('.myClass'); //選擇class不等于myClass的div元素
$('div').filter('.myClass'); //選擇class等于myClass的div元素
$('div').first(); //選擇第1個(gè)div元素
$('div').eq(5); //選擇第6個(gè)div元素
// 從結(jié)果集出發(fā)庇楞,找到周邊元素
$('div').next('p'); //選擇div元素后面的第一個(gè)p元素
$('div').parent(); //選擇div元素的父元素
$('div').closest('form'); //選擇離div最近的那個(gè)form父元素
$('div').children(); //選擇div的所有子元素
$('div').siblings(); //選擇div的同級(jí)元素
三、鏈?zhǔn)讲僮?br> 基于dom樹否纬,每一步操作都返回的是一個(gè)dom對(duì)象
// 找到div元素 =》 選擇其中的h3元素 =》 選擇第三個(gè)h3元素 =》 將他的內(nèi)容改為hello
// =>后退一步到選擇h3那步 =》 選中第一個(gè)h3 =》 講他的內(nèi)容改為world
$('div').find('h3').eq(2).html('Hello').end().eq(0).html('World');
四吕晌、元素操作:取值、賦值
使用同一個(gè)函數(shù)临燃,來完成取值(getter)和賦值(setter)睛驳,即"取值器"與"賦值器"合一。到底是取值還是賦值谬俄,由函數(shù)的參數(shù)決定。
$('h1').html(); //html()沒有參數(shù)弃理,表示取出h1的值
$('h1').html('Hello'); //html()有參數(shù)Hello溃论,表示對(duì)h1進(jìn)行賦值
// 常用取值賦值函數(shù)
.html() 取出或設(shè)置html內(nèi)容
.text()取出或設(shè)置text內(nèi)容
.attr()取出或設(shè)置某個(gè)屬性的值
.width() 取出或設(shè)置某個(gè)元素的寬度
.height()取出或設(shè)置某個(gè)元素的高度
.val()取出某個(gè)表單元素的值
如果結(jié)果集包含多個(gè)元素,那么賦值的時(shí)候痘昌,將對(duì)其中所有的元素賦值钥勋;取值的時(shí)候,則是只取出第一個(gè)元素的值(.text()例外辆苔,它取出所有元素的text內(nèi)容)
五算灸、移動(dòng)
提供兩組方法,來操作元素在網(wǎng)頁中的位置移動(dòng)驻啤。一組方法是直接移動(dòng)該元素菲驴,另一組方法是移動(dòng)其他元素,使得目標(biāo)元素達(dá)到我們想要的位置骑冗。
假定我們選中了一個(gè)div元素赊瞬,需要把它移動(dòng)到p元素后面。
$('div').insertAfter($('p')); // 第一種返回div元素
$('p').after($('div')); // 第二種返回p元素
// 類似的
.insertAfter()和.after():在現(xiàn)存元素的外部贼涩,從后面插入元素
.insertBefore()和.before():在現(xiàn)存元素的外部巧涧,從前面插入元素
.appendTo()和.append():在現(xiàn)存元素的內(nèi)部,從后面插入元素
.prependTo().prepend():在現(xiàn)存元素的內(nèi)部遥倦,從前面插入元素
六谤绳、元素的復(fù)制、刪除袒哥、創(chuàng)建
復(fù)制:.clone()
刪除:.remove()和.detach()
清空:.empty()
七缩筛、工具方法
它是定義在jQuery構(gòu)造函數(shù)上的方法,即jQuery.method()堡称,所以可以直接使用歪脏。而那些操作元素的方法,是定義在構(gòu)造函數(shù)的prototype對(duì)象上的方法粮呢,即jQuery.prototype.method()婿失,所以必須生成實(shí)例(即選中元素)后使用钞艇。如果不理解這種區(qū)別,問題也不大豪硅,只要把工具方法理解成哩照,是像javascript原生函數(shù)那樣,可以直接使用的方法就行了懒浮。
八飘弧、事件綁定
所有的事件處理函數(shù),都可以接受一個(gè)事件對(duì)象(event object)作為參數(shù)
$('p').click(function(){
alert('Hello');
});
.blur() 表單元素失去焦點(diǎn)砚著。
.change() 表單元素的值發(fā)生變化
.click() 鼠標(biāo)單擊
.dblclick() 鼠標(biāo)雙擊
.focus() 表單元素獲得焦點(diǎn)
.focusin() 子元素獲得焦點(diǎn)
.focusout() 子元素失去焦點(diǎn)
.hover() 同時(shí)為mouseenter和mouseleave事件指定處理函數(shù)
.keydown() 按下鍵盤(長(zhǎng)時(shí)間按鍵次伶,只返回一個(gè)事件)
.keypress() 按下鍵盤(長(zhǎng)時(shí)間按鍵,將返回多個(gè)事件)
.keyup() 松開鍵盤
.load() 元素加載完畢
.mousedown() 按下鼠標(biāo)
.mouseenter() 鼠標(biāo)進(jìn)入(進(jìn)入子元素不觸發(fā))
.mouseleave() 鼠標(biāo)離開(離開子元素不觸發(fā))
.mousemove() 鼠標(biāo)在元素內(nèi)部移動(dòng)
.mouseout() 鼠標(biāo)離開(離開子元素也觸發(fā))
.mouseover() 鼠標(biāo)進(jìn)入(進(jìn)入子元素也觸發(fā))
.mouseup() 松開鼠標(biāo)
.ready() DOM加載完成
.resize() 瀏覽器窗口的大小發(fā)生改變
.scroll() 滾動(dòng)條的位置發(fā)生變化
.select() 用戶選中文本框中的內(nèi)容
.submit() 用戶遞交表單
.toggle() 根據(jù)鼠標(biāo)點(diǎn)擊的次數(shù)稽穆,依次運(yùn)行多個(gè)函數(shù)
.unload() 用戶離開頁面
.bind():
$('input').bind(
'click change', //同時(shí)綁定click和change事件
function() {
alert('Hello');
}
);
.one():
$("p").one("click", function() {
alert("Hello"); //只運(yùn)行一次冠王,以后的點(diǎn)擊不會(huì)運(yùn)行
});
.unbind
$('p').unbind('click');
對(duì)于事件函數(shù)的參數(shù),在事件處理函數(shù)中舌镶,可以用this關(guān)鍵字柱彻,返回事件針對(duì)的DOM元素
event.pageX 事件發(fā)生時(shí),鼠標(biāo)距離網(wǎng)頁左上角的水平距離
event.pageY 事件發(fā)生時(shí)餐胀,鼠標(biāo)距離網(wǎng)頁左上角的垂直距離
event.type 事件的類型(比如click)
event.which 按下了哪一個(gè)鍵
event.data 在事件對(duì)象上綁定數(shù)據(jù)哟楷,然后傳入事件處理函數(shù)
event.target 事件針對(duì)的網(wǎng)頁元素
event.preventDefault() 阻止事件的默認(rèn)行為(比如點(diǎn)擊鏈接,會(huì)自動(dòng)打開新頁面)
event.stopPropagation() 停止事件向上層元素冒泡
有兩種方法否灾,可以自動(dòng)觸發(fā)一個(gè)事件卖擅。一種是直接使用事件函數(shù),另一種是使用.trigger()或.triggerHandler()墨技。
$('a').click();
$('a').trigger('click');
九磨镶、特殊效果(動(dòng)畫)
.fadeIn() 淡入
.fadeOut() 淡出
.fadeTo() 調(diào)整透明度
.hide() 隱藏元素
.show() 顯示元素
.slideDown() 向下展開
.slideUp() 向上卷起
.slideToggle() 依次展開或卷起某個(gè)元素
.toggle() 依次展示或隱藏某個(gè)元素
.show()和.hide():元素顯示或隱藏,除了這兩個(gè)之外健提,所有其他特效的默認(rèn)執(zhí)行時(shí)間都是400ms(毫秒)琳猫,但是可以通過傳數(shù)字參數(shù),改變這個(gè)設(shè)置
.animate()
$('div').animate(
{
left : "+=50", //不斷右移
opacity : 0.25 //指定透明度
},
300, // 持續(xù)時(shí)間
function() { alert('done!'); } //回調(diào)函數(shù)
);
.stop()和.delay()用來停止或延緩特效的執(zhí)行
$.fx.off如果設(shè)置為true私痹,則關(guān)閉所有網(wǎng)頁特效脐嫂。
十、性能提升
10.1紊遵、選擇器的選擇账千,上面分析了
10.2、不要濫用jQuery暗膜,有原生方法可以使用的場(chǎng)合匀奏,盡量避免使用jQuery。以最簡(jiǎn)單的選擇器為例学搜,document.getElementById("foo")要比$("#foo")快10多倍
$('a').click(function(){
// 點(diǎn)擊a元素后娃善,彈出該元素的id屬性论衍。為了獲取這個(gè)屬性,必須連續(xù)兩次調(diào)用jQuery聚磺,第一次是$(this)坯台,第二次是attr('id')。
alert($(this).attr('id'));
// 應(yīng)該直接采用原生方法瘫寝,this.id的速度比$(this).attr('id')快了20多倍蜒蕾。
// alert(this.id);
});
10.3、做好緩存
選中某一個(gè)網(wǎng)頁元素焕阿,是開銷很大的步驟咪啡。所以,使用選擇器的次數(shù)應(yīng)該越少越好暮屡,并且盡可能緩存選中的結(jié)果撤摸,便于以后反復(fù)使用。
jQuery('#top').find('p.classA');
jQuery('#top').find('p.classB');
// 應(yīng)該改成
var cached = jQuery('#top');
cached.find('p.classA');
cached.find('p.classB');
10.4栽惶、采用鏈?zhǔn)綄懛ǎ好恳徊綍?huì)自動(dòng)緩存
10.5愁溜、事件委托
在父元素上綁定一次疾嗅,而不用重復(fù)在子元素上綁定外厂,也就是子元素"委托"父元素處理這個(gè)事件。
$("table").on("click", "td", function(){
$(this).toggleClass("click");
});
//更好的寫法代承,則是把事件綁定在document對(duì)象上面
$(document).on("click", "td", function(){
$(this).toggleClass("click");
});
// 取消事件綁定
$(document).off("click", "td");
10.6汁蝶、少改動(dòng)DOM
不要頻繁使用.append()、.insertBefore()和.insetAfter()這樣的方法论悴。如果要插入多個(gè)元素掖棉,就先把它們合并,然后再一次性插入膀估。
如果你要對(duì)一個(gè)DOM元素進(jìn)行大量處理幔亥,應(yīng)該先用.detach()方法,把這個(gè)元素從DOM中取出來察纯,處理完畢以后帕棉,再重新插回文檔。
如果你要在DOM元素上儲(chǔ)存數(shù)據(jù)
var elem = $('#elem');
// 不好的寫法
elem.data(key,value);
// 好的寫法
$.data(elem[0],key,value);
插入html代碼的時(shí)候饼记,瀏覽器原生的innterHTML()方法比jQuery對(duì)象的html()更快
10.7香伴、正確使用循環(huán)
如果可以使用復(fù)雜的選擇器直接選中元素,就不要使用循環(huán)具则,去一個(gè)個(gè)辨認(rèn)元素即纲。javascript原生循環(huán)方法for和while,要比jQuery的.each()方法快博肋,應(yīng)該優(yōu)先使用原生方法
10.8低斋、少生成jQuery對(duì)象
每當(dāng)你使用一次選擇器(比如$('#id'))蜂厅,就會(huì)生成一個(gè)jQuery對(duì)象。jQuery對(duì)象是一個(gè)很龐大的對(duì)象拔稳,帶有很多屬性和方法葛峻,會(huì)占用不少資源。所以巴比,盡量少生成jQuery對(duì)象术奖。
許多jQuery方法都有兩個(gè)版本,一個(gè)是供jQuery對(duì)象使用的版本轻绞,另一個(gè)是供jQuery函數(shù)使用的版本采记。后一種針對(duì)jQuery函數(shù)的版本不通過jQuery對(duì)象操作,所以相對(duì)開銷較小政勃,速度快
var $text = $("#text");
var $ts = $text.text(); // not ok
var $ts = $.text($text); //ok
10.9唧龄、選擇作用域鏈短的方法
avascript的變量采用鏈?zhǔn)阶饔糜颉Wx取變量的時(shí)候奸远,先在當(dāng)前作用域?qū)ふ以撟兞考裙祝绻也坏剑颓巴弦粚拥淖饔糜驅(qū)ふ以撟兞坷僚选_@樣的設(shè)計(jì)丸冕,使得讀取局部變量比讀取全局變量快得多。
10.10薛窥、用PUB/SUB模式管理事件
11胖烛、關(guān)于defer對(duì)象:
jQuery的回調(diào)函數(shù)解決方案
// 傳統(tǒng)寫法
$.ajax({
url: "test.html",
success: function(){
alert("哈哈,成功了诅迷!");
},
error:function(){
alert("出錯(cuò)啦佩番!");
}
});
// 新的寫法,高于1.5.0版本
// $.ajax()操作完成后罢杉,如果使用的是低于1.5.0版本的jQuery趟畏,返回的是XHR對(duì)象,你沒法進(jìn)行鏈?zhǔn)讲僮魈沧猓蝗绻哂?.5.0版本赋秀,返回的是deferred對(duì)象,可以進(jìn)行鏈?zhǔn)讲僮?$.ajax("test.html")
.done(function(){ alert("哈哈持际,成功了沃琅!"); })
.fail(function(){ alert("出錯(cuò)啦!"); });
幾點(diǎn)好處:
11.1蜘欲、回調(diào)函數(shù)可以添加多個(gè)益眉,按照添加順序執(zhí)行
$.ajax("test.html")
.done(function(){ alert("哈哈,成功了!");} )
.fail(function(){ alert("出錯(cuò)啦郭脂!"); } )
.done(function(){ alert("第二個(gè)回調(diào)函數(shù)年碘!");} );
11.2、能為多個(gè)函數(shù)指定回調(diào)函數(shù)
$.when($.ajax("test1.html"), $.ajax("test2.html"))
.done(function(){ alert("哈哈展鸡,成功了屿衅!"); })
.fail(function(){ alert("出錯(cuò)啦!"); });
11.3莹弊、不局限于ajax操作
// 這是一個(gè)很費(fèi)時(shí)間的函數(shù)
var wait = function(){
var tasks = function(){
alert("執(zhí)行完畢涤久!");
};
setTimeout(tasks,5000);
};
// 這種方式done()方法會(huì)立即執(zhí)行,起不到回調(diào)函數(shù)的作用忍弛。原因在于$.when()的參數(shù)只能是deferred對(duì)象响迂,所以必須對(duì)wait()進(jìn)行改寫
$.when(wait())
.done(function(){ alert("哈哈,成功了细疚!"); })
.fail(function(){ alert("出錯(cuò)啦蔗彤!"); });
//對(duì)wait的改寫,然后就可以愉快的用when了
var dtd = $.Deferred(); // 新建一個(gè)deferred對(duì)象疯兼,這里有點(diǎn)問題然遏,他是全局變量,執(zhí)行狀態(tài)可以從外部改變
var wait = function(dtd){
var tasks = function(){
alert("執(zhí)行完畢吧彪!");
dtd.resolve(); // 改變deferred對(duì)象的執(zhí)行狀態(tài)
};
setTimeout(tasks,5000);
return dtd;
};
$.when(wait(dtd))
.done(function(){ alert("哈哈待侵,成功了!"); })
.fail(function(){ alert("出錯(cuò)啦来氧!"); });
上面有一個(gè)重點(diǎn):dtd.resolve();
jQuery規(guī)定诫给,deferred對(duì)象有三種執(zhí)行狀態(tài)----未完成香拉,已完成和已失敗啦扬。如果執(zhí)行狀態(tài)是"已完成"(resolved),deferred對(duì)象立刻調(diào)用done()方法指定的回調(diào)函數(shù);如果執(zhí)行狀態(tài)是"已失敗"凫碌,調(diào)用fail()方法指定的回調(diào)函數(shù)扑毡;如果執(zhí)行狀態(tài)是"未完成",則繼續(xù)等待盛险,或者調(diào)用progress()方法指定的回調(diào)函數(shù)(jQuery1.7版本添加)瞄摊。
前面部分的ajax操作時(shí),deferred對(duì)象會(huì)根據(jù)返回結(jié)果苦掘,自動(dòng)改變自身的執(zhí)行狀態(tài)换帜;但是,在wait()函數(shù)中鹤啡,這個(gè)執(zhí)行狀態(tài)必須由程序員手動(dòng)指定惯驼。dtd.resolve()的意思是,將dtd對(duì)象的執(zhí)行狀態(tài)從"未完成"改為"已完成",從而觸發(fā)done()方法祟牲。
類似的還有defer.reject():將dtd對(duì)象的執(zhí)行狀態(tài)從"未完成"改為"已失敗"隙畜,從而觸發(fā)fail()方法。
上面說的全局變量從外面改變執(zhí)行狀態(tài)的問題说贝,可以用promise解決:
var dtd = $.Deferred(); // 新建一個(gè)Deferred對(duì)象
var wait = function(dtd){
var tasks = function(){
alert("執(zhí)行完畢议惰!");
dtd.resolve(); // 改變Deferred對(duì)象的執(zhí)行狀態(tài)
};
setTimeout(tasks,5000);
return dtd.promise(); // 返回promise對(duì)象
};
var d = wait(dtd); // 新建一個(gè)d對(duì)象,改為對(duì)這個(gè)對(duì)象進(jìn)行操作
$.when(d)
.done(function(){ alert("哈哈乡恕,成功了言询!"); })
.fail(function(){ alert("出錯(cuò)啦!"); });
上面這種寫法傲宜,wait返回了一個(gè)promise對(duì)象倍试,可以對(duì)他wait,但是還有更好的寫法:將dtd變成wait內(nèi)部變量
var wait = function(dtd){
var dtd = $.Deferred(); //在函數(shù)內(nèi)部蛋哭,新建一個(gè)Deferred對(duì)象
var tasks = function(){
alert("執(zhí)行完畢县习!");
dtd.resolve(); // 改變Deferred對(duì)象的執(zhí)行狀態(tài)
};
setTimeout(tasks,5000);
return dtd.promise(); // 返回promise對(duì)象
};
$.when(wait())
.done(function(){ alert("哈哈,成功了谆趾!"); })
.fail(function(){ alert("出錯(cuò)啦躁愿!"); });
針對(duì)從外部改變執(zhí)行狀態(tài)的問題,還可以有另一種方式:
// wait還是最開始的wait沪蓬,使用deferred對(duì)象的建構(gòu)函數(shù)$.Deferred()
$.Deferred(wait)
.done(function(){ alert("哈哈彤钟,成功了!"); })
.fail(function(){ alert("出錯(cuò)啦跷叉!"); });
或者在wait上部署deferred接口:逸雹??云挟?不太理解
var dtd = $.Deferred(); // 生成Deferred對(duì)象
var wait = function(dtd){
var tasks = function(){
alert("執(zhí)行完畢梆砸!");
dtd.resolve(); // 改變Deferred對(duì)象的執(zhí)行狀態(tài)
};
setTimeout(tasks,5000);
};
dtd.promise(wait); //在wait對(duì)象上部署Deferred接口拿霉。正是因?yàn)橛辛诉@一行扰楼,后面才能直接在wait上面調(diào)用done()和fail()波桩。
wait.done(function(){ alert("哈哈轻抱,成功了椰憋!"); })
.fail(function(){ alert("出錯(cuò)啦唤殴!"); });
wait(dtd);