返回首页 JavaScript 核心技术指南

前端 JavaScript 框架

简介

jQuery是目前应用最为广泛,最为优秀的Ajax/JavaScript开源框架之一,有数以千万记的用户,更有多不胜数的技术文档与之相关,在一定程度上,jQuery如其所宣扬的那样,改变了人们编写JavaScript的方式。

jQuery通过提供CSS标准的选择器来对页面元素进行选择,然后对这些元素组成的一个列表进行某些操作,参与过页面开发的人员都知道,基于WEB的UI实际上要做的事情就是:

  • 找到页面上的某个/某些元素
  • 改变这些元素的属性或者样式
  • 绑定一些事件处理程序在这些元素上

为了对开发者更友好,jQuery使用了独特的链式操作,使得可以使用尽可能的代码来完成尽可能多的任务。就个人而言,jQuery是我个人最喜欢的JavaScript框架。我们可以通过一些例子来看看jQuery是怎样工作的。

假设我们有一个table,如果给table加上斑马线的话,用户可以更清晰的看清楚每一行,整个页面也更有层次感,但是问题是我们的页面已经做好了,我不想再对页面做修改!

这样单调的一种颜色很容易使用户的视觉产生疲劳,我们应该为偶数行添加浅绿色的背景,像这样:

这样效果就好多了,要做成这种效果,用jQuery需要多少代码呢?一行!我们来看看如何用一行代码完成这样的效果:首先,我们找到这个table,然后告诉jQuery,给这个table中的所有偶数行都添加一个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)表示为偶数的孩子。

完整的代码如下:

$(document).ready(function(){  
    $("div#informationTable table tr:nth-child(even)")  
    .addClass("striped");  
});  

这段代码表示,当文档加载完成后($(document).ready()),调用一个匿名的函数,这个函数的函数体为我们上面分析过的,找到table的所有偶数列,为这些列添加背景色(通过使用css类”striped”)。

事实上,jQuery深受开发人员青睐的更深层次的原因可能要归功于贯穿于其中的编程思想,如果仔细审视jQuery的代码,你应该会发现,其中的集合的概念以及对集合的各种操作,与函数式语言lisp是不谋而合的,比如map,filter,以及grep等等。

我们可以来看看这样几个简单示例:

jQuery.grep对列表进行过滤,并返回过滤后的列表。我们来看一个例子,首先定义一个人员列表,每个条目包含name和age字段,现在要找出所有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中的静态方法。console.dir是Firefox或者Chrome的调试助手,在chrome下的结果如下:

再来看一下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字段的值转换为大写。Map的修改是直接体现在原始列表上的,结果如下:

jQuery本身不如ExtJs那样可以轻松而快速的开发出华丽的UI,但是jQuery本身提供的插件机制为使用jQuery方式快速开发华丽的UI提供了可能,比如jQuery-UI, EasyUI等插件的出现,使得用户可以向使用jQuery那样,快速的生成UI,提高开发速度。

jQuery 基础

jQuery 选择器

jQuery最强大易用的即是它提供的选择器,它支持CSS选择器及其扩展,很方便已经熟悉传统web开发模式的用户快速过渡到jQuery上来。比如下面这些常用的CSS选择器:

  • div.highlight 选择CSS类highlight的所有div元素
  • table#tabid 选择ID为tabid的table元素
  • a#aid.aclass 选择ID为aid,CSS类为aclass的链接元素

这些选择器均可直接在jQuery中使用,只需要将选择器包装在$()中即可。jQuery的选择器完全兼容CSS3选择器。这为跨浏览器的web应用提供了极大的便利。

除了这些基本的CSS选择器外,jQuery提供了更丰富的选择器,如通过位置选择:

选择器 作用
:first 选择第一个匹配
:last 选择最后一个匹配
:first-child 选择第一个字元素
:last-child 选择最后一个子元素
:nth-child(n) 选择第n个子元素
:even 及 :odd 选择偶数/奇数子元素集
:eq(n) 第n个元素(从0开始)
:gt(n) 选择第n个元素之后的元素集
:lt(n) 选择第n个元素之前的元素集

比如:

  • li a:first 匹配在列表(<li>)元素下的第一个链接(<a>)元素。
  • table tbody td:nth-child(5)返回table的第6列元素集。

自定义选择器:

选择器 作用
:button 选择按钮
:checkbox 选择复选框
:checked 选择已经选中的复选框/单选框
:hidden 选择属性为隐藏的元素
:enable 选择启用的元素
:disable 选择禁用的元素
:image 选择图片
:input 选择输入框
:radio 选择单选框
:not(filter) 反向选择器

应该注意的是,这些选择器可以组合使用,这样会给我们提供极大的方便,比如:

  • :input:enable 选择已经启用的文本框元素
  • :checkbox:checked 选择已经选择的复选框元素

对 DOM 的操作

在实际应用中,经常需要操作DOM元素,比如插入一段HTML到指定位置,删除某些被选择的DOM段,修改某些元素的内容等。

例如有一个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的方框,我们要动态的为这个div添加一个子元素,子元素的ID为child:

$(function(){  
    var container = $("div#container");  
    $("<div id='child'></div>").appendTo(container);  
});  

运行结果如上图所示。

再进一步,我们为页面添加一个按钮(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框。

对 CSS 的操作

使用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是否已经被yellow修饰过,如果已经被修饰过,则移除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");  
});  

页面效果如下:

点击red按钮之后,base添加了red-region的CSS类,变为红色:

在使用jQuery选择器选择到预期的元素集之后,我们可以修改器CSS,来完成页面的动态化。动态修改CSS非常简单:

var base = $("div#base");  
base.css('width', '300px');  
base.css({  
   'width' : '300px',  
   'height' : '300px',  
   'background' : 'green'  
});  

使用css函数,可以进行一个值的修改,同样可以传入一个集合,整体进行修改。

事件处理

事实上,在上边的例子中很多地方已经涉及到jQuery事件处理部分了。jQuery不但提供基本的bind/unbind来负责注册及删除事件处理器,同时还提供很多更方便web开发的的助手函数,如toggle/hover等。 注册一个事件处理器非常容易:

var base = $("div#base");  
base.bind('click', function(event){  
   alert($(this).width()+", "+$(this).height());  
});  

当鼠标单击ID为base的div时,触发该事件。使用unbind将事件处理器删除。我们来看一个小例子:

单击bind按钮时,我们为按钮上方的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则会弹出一个对话框:

点击unbind之后,div将不会再处理click事件。有时候,我们会需要为单击的次数为奇数和偶数时注册不同的事件处理器,如第一次单击时将panel的背景色变为红色,再次单击则将背景色变为黄色,这时候我们可以使用toggle函数:

var base = $("div#base");  

base.toggle(  
   function(){  
       $(this).css('background', 'red');  
   },  
   function(){  
       $(this).css('background', 'yellow');  
   }  
);  

当然,更多的是处理鼠标移入/移出事件的hover,当用户在页面上移动鼠标,将展现不同的视觉效果:

base.hover(  
   function(event){  
       $(this).css('background', 'red');  
   },  
   function(event){  
       $(this).css('background', 'yellow');    
   }  
);  

实用函数

jQuery除了提供对DOM操作的API之外,还提供了操作普通JavaScript对象的一些函数,这些函数均已”$.”开头,非常方便易用。这些实用函数包括:对字符串操作的函数,遍历对象的函数,过滤数组中元素等。

我们来看一些小例子:

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上:

$.grep/$.map两个实用函数已经在第一小节做过基本的讲解,这里仅列举出两个函数的原型:

/** 
 * array    : 要过滤的数组对象 
 * callback : 过滤条件 
 * invert   : 是否启用反转,如果启用,则符合callback的将被过滤 
 */  
$.grep(array, callback, invert);  

/** 
 * array    : 需要做转换的数组对象 
 * callback : 对数组中元素的映射函数 
 */  
$.map(array, callback);  

有时候,我们可能需要合并数个对象为一个对象,覆盖其中重复的项等:

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属性。

总而言之,jQuery是一个小巧,实用,易用且功能强大的框架。使用它,可以将原本复杂难懂的JavaScript代码压缩至很小,而且更容易维护,代码更加优美。jQuery可以称得上是web上的lisp。

jQuery 实例

在这一小节,我们将使用jQuery开发一个简单的todo管理器jqtodo。jqtodo使用httpd+php脚本作为后台,数据库使用小巧的sqlite。jqtodo简单到仅支持新建一个todo及对之前所有todo的查询操作。

页面布局上,有一个输入框和一个按钮,用户在输入框中填写待办事项,然后点击按钮,即可将这条待办事项添加到数据库中,并同时将页面的待办事项列表更新:

简单起见,这里没有对用户的输入做任何校验,如果插入成功,则展示在列表中:

我们需要用jQuery做的事情如下:

  • 当点击add item时,将文本框中的内容取出,并发送给服务器
  • 当服务器完成并响应时,我们需要及时的更新列表
  • 当用户首次进入此页面时,需要将历史中的待办事项列出来

在页面上定义一个div,其id为itemlist,则当进入页面时,可以通过jQuery.ajax来获取数据库信息,并填充页面:

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的页面,该页面负责查询数据库,并将结构及作为json数组的格式返回,并将数据集存放在”dataset”属性中,当成功时,我们可以遍历这个数组,并动态的创建条目,为条目添加属性及CSS类,最后将其添加到id为itemlist的div上展现。 类似的,页面上有一个id为add的按钮,单击该按钮将触发以下事件:

$("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);  
    }  
});  

首先获取文本框中的字符串,并做一下简单的非空校验。通过校验后则调用additem函数进行查询及页面更新:

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);  
       }  
    });  
}  

在这个函数中,只是简单的组织了需要POST的数据,然后使用jQuery.ajax异步的更新页面中的待办事项列表。

使用jQuery,可以在很短小的代码量中完成很多工作,一般而言,简洁的代码更容易维护和扩展。哪怕仅仅只是从代码的可读性和美学的意义上来讲,jQuery也非常值得一试。