jQuery是目前應用最為廣泛,最為優(yōu)秀的Ajax/JavaScript開源框架之一,有數(shù)以千萬記的用戶,更有多不勝數(shù)的技術(shù)文檔與之相關(guān),在一定程度上,jQuery如其所宣揚的那樣,改變了人們編寫JavaScript的方式。
jQuery通過提供CSS標準的選擇器來對頁面元素進行選擇,然后對這些元素組成的一個列表進行某些操作,參與過頁面開發(fā)的人員都知道,基于WEB的UI實際上要做的事情就是:
為了對開發(fā)者更友好,jQuery使用了獨特的鏈式操作,使得可以使用盡可能的代碼來完成盡可能多的任務。就個人而言,jQuery是我個人最喜歡的JavaScript框架。我們可以通過一些例子來看看jQuery是怎樣工作的。
假設我們有一個table,如果給table加上斑馬線的話,用戶可以更清晰的看清楚每一行,整個頁面也更有層次感,但是問題是我們的頁面已經(jīng)做好了,我不想再對頁面做修改!
http://wiki.jikexueyuan.com/project/javascript-core/images/jq.png" alt="" />
這樣單調(diào)的一種顏色很容易使用戶的視覺產(chǎn)生疲勞,我們應該為偶數(shù)行添加淺綠色的背景,像這樣:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq1.png" alt="" />
這樣效果就好多了,要做成這種效果,用jQuery需要多少代碼呢?一行!我們來看看如何用一行代碼完成這樣的效果:首先,我們找到這個table,然后告訴jQuery,給這個table中的所有偶數(shù)行都添加一個css偽類:
$("div#informationTable table tr:nth-child(even)")
.addClass("striped");
“div#informationTable table tr:nth-child(even)”為一個CSS標準的選擇器,表示在一個id為informationTable的div的孩子中,找到所有的table,tr是table的孩子,并使行,nth-child(even)表示為偶數(shù)的孩子。
完整的代碼如下:
$(document).ready(function(){
$("div#informationTable table tr:nth-child(even)")
.addClass("striped");
});
這段代碼表示,當文檔加載完成后($(document).ready()),調(diào)用一個匿名的函數(shù),這個函數(shù)的函數(shù)體為我們上面分析過的,找到table的所有偶數(shù)列,為這些列添加背景色(通過使用css類”striped”)。
事實上,jQuery深受開發(fā)人員青睞的更深層次的原因可能要歸功于貫穿于其中的編程思想,如果仔細審視jQuery的代碼,你應該會發(fā)現(xiàn),其中的集合的概念以及對集合的各種操作,與函數(shù)式語言lisp是不謀而合的,比如map,filter,以及grep等等。
我們可以來看看這樣幾個簡單示例:
jQuery.grep對列表進行過濾,并返回過濾后的列表。我們來看一個例子,首先定義一個人員列表,每個條目包含name和age字段,現(xiàn)在要找出所有age大于24歲的人員,并以列表的形式返回:
$(document).ready(function(){
var person = [
{name : "jack", age : 26},
{name : "johb", age : 23},
{name : "smith", age : 20},
{name : "abruzzi", age : 26},
{name : "juntao", age : 25},
{name : "jim", age : 24},
{name : "bob", age : 24}
];
var gt23s = $.grep(person, function(item){
return item.age > 24;
});
console.dir(gt23s);
});
jQuery的工具方法定義在jQuery對象上,類似于Java中的靜態(tài)方法。console.dir是Firefox或者Chrome的調(diào)試助手,在chrome下的結(jié)果如下:
再來看一下map的例子:
$(document).ready(function(){
var person = [
{name : "jack", age : 26},
{name : "johb", age : 23},
{name : "smith", age : 20},
{name : "abruzzi", age : 26},
{name : "juntao", age : 25},
{name : "jim", age : 24},
{name : "bob", age : 24}
];
var mapped = $.map(person, function(item){
return item.name = item.name.toUpperCase();
});
console.dir(person);//原始的person列表已被修改
});
我們將person列表中的每一個元素的name字段的值轉(zhuǎn)換為大寫。Map的修改是直接體現(xiàn)在原始列表上的,結(jié)果如下:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq2.png" alt="" />
jQuery本身不如ExtJs那樣可以輕松而快速的開發(fā)出華麗的UI,但是jQuery本身提供的插件機制為使用jQuery方式快速開發(fā)華麗的UI提供了可能,比如jQuery-UI, EasyUI等插件的出現(xiàn),使得用戶可以向使用jQuery那樣,快速的生成UI,提高開發(fā)速度。
jQuery最強大易用的即是它提供的選擇器,它支持CSS選擇器及其擴展,很方便已經(jīng)熟悉傳統(tǒng)web開發(fā)模式的用戶快速過渡到jQuery上來。比如下面這些常用的CSS選擇器:
這些選擇器均可直接在jQuery中使用,只需要將選擇器包裝在$()中即可。jQuery的選擇器完全兼容CSS3選擇器。這為跨瀏覽器的web應用提供了極大的便利。
除了這些基本的CSS選擇器外,jQuery提供了更豐富的選擇器,如通過位置選擇:
| 選擇器 | 作用 |
|---|---|
| :first | 選擇第一個匹配 |
| :last | 選擇最后一個匹配 |
| :first-child | 選擇第一個字元素 |
| :last-child | 選擇最后一個子元素 |
| :nth-child(n) | 選擇第n個子元素 |
| :even 及 :odd | 選擇偶數(shù)/奇數(shù)子元素集 |
| :eq(n) | 第n個元素(從0開始) |
| :gt(n) | 選擇第n個元素之后的元素集 |
| :lt(n) | 選擇第n個元素之前的元素集 |
比如:
(<li>)元素下的第一個鏈接(<a>)元素。自定義選擇器:
| 選擇器 | 作用 |
|---|---|
| :button | 選擇按鈕 |
| :checkbox | 選擇復選框 |
| :checked | 選擇已經(jīng)選中的復選框/單選框 |
| :hidden | 選擇屬性為隱藏的元素 |
| :enable | 選擇啟用的元素 |
| :disable | 選擇禁用的元素 |
| :image | 選擇圖片 |
| :input | 選擇輸入框 |
| :radio | 選擇單選框 |
| :not(filter) | 反向選擇器 |
應該注意的是,這些選擇器可以組合使用,這樣會給我們提供極大的方便,比如:
在實際應用中,經(jīng)常需要操作DOM元素,比如插入一段HTML到指定位置,刪除某些被選擇的DOM段,修改某些元素的內(nèi)容等。
例如有一個HTML頁面:
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css" />
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript" src="selector.js"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
樣式表為:
div#container{
background:blue;
border:1px solid black;
width:200px;
height:200px;
}
div#child{
background:yellow;
border:1px solid black;
width:100px;
height:100px;
}
container是一個藍色的200x200的方框,我們要動態(tài)的為這個div添加一個子元素,子元素的ID為child:
$(function(){
var container = $("div#container");
$("<div id='child'></div>").appendTo(container);
});
http://wiki.jikexueyuan.com/project/javascript-core/images/jq5.png" alt="" />
運行結(jié)果如上圖所示。
再進一步,我們?yōu)轫撁嫣砑右粋€按鈕(clean),點擊此按鈕將清除新添加的黃色child方框。
<input type="button" id="clean" value="clean" />
并添加JavaScript代碼:
$(function(){
var container = $("div#container");
$("<div id='child'></div>").appendTo(container);
$("input#clean").click(function(){
container.find("#child").remove();
});
});
單擊clean按鈕之后,將會移除新添加的child框。
http://wiki.jikexueyuan.com/project/javascript-core/images/jq6.png" alt="" />
使用jQuery,可以很方便的對CSS類進行添加/刪除/toggle等操作,我們來看一個簡單的示例: 首先定義三個CSS類:base,red-region,yellow-region:
.base{
background:white;
border:1px solid black;
width:200px;
height:200px;
}
.red-region{
background:red;
border:1px solid blue;
width:200px;
height:200px;
}
.yellow-region{
background:yellow;
border:1px solid green;
width:200px;
height:200px;
}
定義一個ID為base的面板,兩個按鈕:red和yellow。當點擊red時,判斷base是否已經(jīng)被yellow修飾過,如果已經(jīng)被修飾過,則移除CSS類yellow-region。點擊yellow時情形類似:
var base = $("div#base");
$("input#red").click(function(){
if(base.hasClass("yellow-region")){
base.removeClass("yellow-region");
}
$("div#base").addClass("red-region");
});
$("input#yellow").click(function(){
if(base.hasClass("red-region")){
base.removeClass("red-region");
}
$("div#base").addClass("yellow-region");
});
頁面效果如下:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq7.png" alt="" />
點擊red按鈕之后,base添加了red-region的CSS類,變?yōu)榧t色:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq8.png" alt="" />
在使用jQuery選擇器選擇到預期的元素集之后,我們可以修改器CSS,來完成頁面的動態(tài)化。動態(tài)修改CSS非常簡單:
var base = $("div#base");
base.css('width', '300px');
base.css({
'width' : '300px',
'height' : '300px',
'background' : 'green'
});
使用css函數(shù),可以進行一個值的修改,同樣可以傳入一個集合,整體進行修改。
事實上,在上邊的例子中很多地方已經(jīng)涉及到jQuery事件處理部分了。jQuery不但提供基本的bind/unbind來負責注冊及刪除事件處理器,同時還提供很多更方便web開發(fā)的的助手函數(shù),如toggle/hover等。 注冊一個事件處理器非常容易:
var base = $("div#base");
base.bind('click', function(event){
alert($(this).width()+", "+$(this).height());
});
當鼠標單擊ID為base的div時,觸發(fā)該事件。使用unbind將事件處理器刪除。我們來看一個小例子:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq9.png" alt="" />
單擊bind按鈕時,我們?yōu)榘粹o上方的div注冊click事件處理器,點擊unbind時,移除該事件處理器:
$("input#bind").click(function(){
base.bind('click', function(event){
alert($(this).width()+", "+$(this).height());
});
});
$("input#unbind").click(function(){
base.unbind('click');
});
這樣,點擊bind之后,點擊div則會彈出一個對話框:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq10.png" alt="" />
點擊unbind之后,div將不會再處理click事件。有時候,我們會需要為單擊的次數(shù)為奇數(shù)和偶數(shù)時注冊不同的事件處理器,如第一次單擊時將panel的背景色變?yōu)榧t色,再次單擊則將背景色變?yōu)辄S色,這時候我們可以使用toggle函數(shù):
var base = $("div#base");
base.toggle(
function(){
$(this).css('background', 'red');
},
function(){
$(this).css('background', 'yellow');
}
);
當然,更多的是處理鼠標移入/移出事件的hover,當用戶在頁面上移動鼠標,將展現(xiàn)不同的視覺效果:
base.hover(
function(event){
$(this).css('background', 'red');
},
function(event){
$(this).css('background', 'yellow');
}
);
jQuery除了提供對DOM操作的API之外,還提供了操作普通JavaScript對象的一些函數(shù),這些函數(shù)均已”$.”開頭,非常方便易用。這些實用函數(shù)包括:對字符串操作的函數(shù),遍歷對象的函數(shù),過濾數(shù)組中元素等。
我們來看一些小例子:
var obj = {
a : 'apple',
b : 'borland',
c : 'cisco',
d : 'dell'
};
$.each(obj, function(name, value){
var li = $("<li></li>");
li.html("["+name+"]=["+value+"]");
li.appendTo(base);
});
遍歷對象obj,然后將其中的鍵值對拼裝成一個字符串,添加到一個panel上:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq11.png" alt="" />
$.grep/$.map兩個實用函數(shù)已經(jīng)在第一小節(jié)做過基本的講解,這里僅列舉出兩個函數(shù)的原型:
/**
* array : 要過濾的數(shù)組對象
* callback : 過濾條件
* invert : 是否啟用反轉(zhuǎn),如果啟用,則符合callback的將被過濾
*/
$.grep(array, callback, invert);
/**
* array : 需要做轉(zhuǎn)換的數(shù)組對象
* callback : 對數(shù)組中元素的映射函數(shù)
*/
$.map(array, callback);
有時候,我們可能需要合并數(shù)個對象為一個對象,覆蓋其中重復的項等:
var obj1 = {
name : 'juntao',
last : 'qiu',
};
var obj2 = {
addr : 'unknown',
title : 'unknown'
};
var obj3 = {
addr : 'KunMing, Yunnan, China'
};
result = $.extend({}, obj1, obj2, obj3);
$.each(result, function(name, value){
var li = $("<li></li>");
li.html("["+name+"]=["+value+"]");
li.appendTo(base);
});
obj1, obj2, obj3的屬性被合并在一起,并且obj3中的addr屬性覆蓋了obj2中的addr屬性。
http://wiki.jikexueyuan.com/project/javascript-core/images/jq12.png" alt="" />
總而言之,jQuery是一個小巧,實用,易用且功能強大的框架。使用它,可以將原本復雜難懂的JavaScript代碼壓縮至很小,而且更容易維護,代碼更加優(yōu)美。jQuery可以稱得上是web上的lisp。
在這一小節(jié),我們將使用jQuery開發(fā)一個簡單的todo管理器jqtodo。jqtodo使用httpd+php腳本作為后臺,數(shù)據(jù)庫使用小巧的sqlite。jqtodo簡單到僅支持新建一個todo及對之前所有todo的查詢操作。
頁面布局上,有一個輸入框和一個按鈕,用戶在輸入框中填寫待辦事項,然后點擊按鈕,即可將這條待辦事項添加到數(shù)據(jù)庫中,并同時將頁面的待辦事項列表更新:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq13.png" alt="" />
簡單起見,這里沒有對用戶的輸入做任何校驗,如果插入成功,則展示在列表中:
http://wiki.jikexueyuan.com/project/javascript-core/images/jq14.png" alt="" />
我們需要用jQuery做的事情如下:
在頁面上定義一個div,其id為itemlist,則當進入頁面時,可以通過jQuery.ajax來獲取數(shù)據(jù)庫信息,并填充頁面:
var list = $("div#itemlist");
$.ajax({
url : 'queryitems.php',
type : 'GET',
error : function(xhr){
alert(xhr);
},
success : function(obj){
obj = eval('('+obj+')');
var dataset = obj.dataset;
for(var i = 0; i < dataset.length; i++){
var current = dataset[i];
var newitem = $("<div></div>").text(current.desc)
.attr({
"id" : current.itemid,
"time" : current.ctime
})
.addClass("item");
newitem.appendTo(list);
}
}
});
后臺提供一個queryitems.php的頁面,該頁面負責查詢數(shù)據(jù)庫,并將結(jié)構(gòu)及作為json數(shù)組的格式返回,并將數(shù)據(jù)集存放在”dataset”屬性中,當成功時,我們可以遍歷這個數(shù)組,并動態(tài)的創(chuàng)建條目,為條目添加屬性及CSS類,最后將其添加到id為itemlist的div上展現(xiàn)。 類似的,頁面上有一個id為add的按鈕,單擊該按鈕將觸發(fā)以下事件:
$("input#add").click(function(){
var item = $("input#item").val();
if(!item || item.length == 0){
alert("please set the item description");
return false;
}else{
additem(item);
}
});
首先獲取文本框中的字符串,并做一下簡單的非空校驗。通過校驗后則調(diào)用additem函數(shù)進行查詢及頁面更新:
function additem(item){
var dat = "item="+item;
$.ajax({
url : 'additem.php',
type : 'POST',
dataType : 'text',
data : dat,
error : function(xhr){
alert(xhr);
},
success : function(obj){
obj = eval('('+obj+')');
var newitem = $("<div></div>").text(obj.desc)
.attr({
"time" : obj.ctime
})
.addClass("item");
newitem.appendTo(list);
}
});
}
在這個函數(shù)中,只是簡單的組織了需要POST的數(shù)據(jù),然后使用jQuery.ajax異步的更新頁面中的待辦事項列表。
使用jQuery,可以在很短小的代碼量中完成很多工作,一般而言,簡潔的代碼更容易維護和擴展。哪怕僅僅只是從代碼的可讀性和美學的意義上來講,jQuery也非常值得一試。