jQuery学习之核心模块用法及实例

write less, do more.

  jQuery几乎可以说是最流行的前端JavaScript库,最近准备看一下jQuery的源码,学习一下他的编程思路。1.7.2版本的jQuery代码一万多行,短期内必然不可能都理清,所以我只关注了他的核心模块:选择器,DOM操作,事件处理和Ajax等。匆忙中阴差阳错买了第二版的《锋利的jQuery》,回来一看此书好像没怎么讲jQuery的源码,主要还是讲应用于实战,想来我也没系统的学习过jQ,因此就想着先粗略过一遍此书。我非常赞同jQuery的理念:

write less, do more.

一、概述

相对于其它JS库,它的优势也很明显:

  • 轻量级,压缩后只有30KB左右;
  • 强大的选择器,不仅支持CSS选择器,还封装了jQ特有的高级选择器;
  • 可靠的事件处理机制;
  • 完善的ajax;
  • 出色的兼容性,丰富的插件与文档;
  • 链式操作,隐式迭代等机制;

二、jQuery对象

jQuery对象区别于DOM对象,一般来说通过JS选择器document.getElementBy得到的对象是DOM对象,通过jQ选择器得到的是jQuery对象。需要注意的是:

jQuery对象和DOM对象不能使用对方的方法,比如$('#id').innerHTMLdocument.getElementById('id').html()的用法是错误的。

两者的相互转换的方法:

  • jQuery对象转换为DOM对象:使用[index]和get(index)方法,比如$('#id')[0]得到的就是DOM对象;
  • DOM对象转换为jQuery对象:直接使用&()将DOM对象包装起来就可以。

&()是jQuery的工厂函数,粗略看了一下源码的初始化部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;

// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}

// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
······

  其中处理DOM对象部分的大致意思是:判断元素的nodeType1表示元素节点,2表示属性,3表示文字节点,8表示注释等),如果是某一种节点则返回一个装着DOM本身的数组,当然这个数组挂载了众多的jQuery方法。
  上面代码的第一行说明了返回的jQuery对象继承jQ方法是通过修改原型链实现的,当使用某个方法时,如果当前对象没有找到则沿着原型链查找,所有子类共享同样的方法和数据。

三、jQuery选择器

  jQuery选择器支持CSS选择器的语法,同时也遵循CSS选择器的优先级机制:ID选择器权值100,类为10,标签为1,权值求和越高优先级也越高,具体使用方法不再赘述。jQuery选择器的一个优势就是:

操作不存在的元素时不会报错。

因此判断是否选择了元素应该判断长度是否大于0。jQuery选择器大致分为以下几类:

  • 基本选择器:ID,类,标签,集合选择器等;
  • 层次选择器:中间有连字符的,比如后代,兄弟选择器等;
  • 基本过滤选择器:以冒号开始,比如:first,:not(selector)等;
    • 内容过滤选择器::contains(text)表示含有text文本内容的元素,:has表示含有selector选择器匹配元素的元素;
  • 可见性过滤选择器::hidden表示选择所有不可见元素,:visible表示选择所有可见元素;
  • 属性过滤选择器:以[]包裹,格式为:[属性 判别符 值],多个[]串联表示与关系;
  • 子元素过滤器::nth-child,:first-child,:last-child等;
  • 表单属性过滤器:针对表单元素进行过滤::enabled,:disabled,:checked,:selected;

  • 表单选择器:直接选取表单元素,比如:input,:button,:password等;

四、DOM操作

先说一下DOM的定义:

DOM(Document Object Model):文档对象模型,它是一种与浏览器、平台、语言无关的接口,使用该接口可轻松访问页面中所有的标准组件。

DOM操作分三类:

  • DOM core:核心操作,比如getElementBygetAttribute等;
  • HTML-DOM:专门针对html文档的操作,比如document.formsdocument.src,通常会比更简短;
  • CSS-DOM:针对CSS的操作,主要用于获取或设置style对象的属性,如elem.style.color=#ccc

jQuery中的DOM操作

1. 查找节点

查找属性节点直接通过选择器就行,查找属性节点通过attr方法:$('#id').attr(title)表示获取title属性节点的值。

2. 创建节点

通过给$()传入包含html标签的字符串实现,标签中可以包含任意的文本或者属性节点。

3. 插入节点

  • append/appendTo:插入到指定元素内部的最后面;
  • prepend/prependTo:将元素插入到指定元素内部的最前面;
  • after/insertAfter:插入到指定元素外部的紧接着的后面;
  • before/insertBefore:插入到指定元素外部的紧接着的前面;

4. 删除节点

使用remove()方法删除元素及其后代所有节点,使用empty()可以清空元素内部的节点,元素的标签依然会存在。

5. 复制节点

使用clone()方法可以复制一个节点及其后代节点,传入形参true可以复制绑定在元素上的事件。

6. 替换节点

使用replaceWith()进行元素替换,替换后事件自动失效;

7. 包裹节点

wrap()方法可以将匹配元素分别用传入的标签包裹起来:$('id').wrap('<b></b>'),而wrapAll()方法将匹配的元素一起用指定的标签包裹。最后wrapInner()方法是在匹配元素内部对所有后代进行包裹。

jQuery中的属性操作

attr()用于获取元素属性,removeAttr()用于删除属性。addClass()removeClass()分别用于添加和删除类名,toggleClass()用于切换样式,hasClass用于判断是否含有某个样式。html()text()用于获取html和文本值,前一个方法获取的值包括html标签,后者只包含文本。val()用于获取或设置文本框,多选框,单选框的值。

DOM树遍历

DOM树的遍历是前端常用的操作之一,使用jQuery能够大大简化代码,相比原生JS更加高效强大。

  • children():获取匹配元素的子元素集合,只包含子元素,不包含其它后代元素。
  • next()prev():分别获取匹配元素后面和前面紧邻的同辈元素。
  • siblings():获取匹配元素前后所有的同辈元素。
  • closest():获取最近的匹配元素,从当前节点开始逐层往上查找。
  • parent()用于获取每个匹配元素的父级元素,parents()返回多个父节点。

CSS-DOM操作

原生JS中的style对象可用于获取CSS属性,其不足在于不能获取由外部CSS设置的样式,比如一个节点没有直接在行内设置width,而是在CSS样式表中设置了width,那么通过style.width的方式是无法获得宽度的(依然可以用于设置宽度)。在jQuery中无论属性是通过外部CSS导入还是直接拼接在元素里,css()方法都可以获取到属性值。使用css()设置多个属性时,需传入一个对象,里面是需要设置的属性名和值。
height()width()方法用于获取元素实际的大小,默认单位是px。
offset()方法获取元素在当前窗口的相对偏移。包含top和left两个属性。
position()方法用于获取元素相对于最近的一个position被设置为relative或者absolute的祖父节点的相对偏移,同样包含top和left两个属性。
scrollTop()scrollLeft()方法用于获取元素的滚动条距顶端和左侧的距离。

五、jQuery中的事件

  jQuery中最经典的要数$(document).ready()了,这个方法绑定的函数会在DOM树加载完成(图片等可能还未加载完)的时候执行,观察jQuery源码,这个应该是通过先把函数push到一个数组,等到document.readyState === "complete"时再去执行数组里的函数。jQuery中使用bindtypename=方式绑定事件的效果是一样的,用法不再详述,值得注意的是jQuery事件不支持事件捕获。接下来重点说两个方面:自定义事件和on()方法。

自定义事件

jQuery中使用自定义的方法自然并且优雅,方法和绑定一般事件一样,触发时使用trigger函数,并且支持传递数据:

1
2
3
4
$('#id').bind('uesrEvent',function(data){
//do something
});
$('#id').trigger('uesrEvent','data'); //触发事件

on方法

on()方法可以用于绑定一般事件,但是更重要的用处是进行“事件委托”。在为大量DOM元素绑定相同事件时,使用事件委托可以大大提高性能,jQuery中on方法的调用格式如下:

1
2
3
4
5
6
7
8
9
10
$(element).on(event         //待绑定的事件,支持自定义事件,element是被委托的元素
[,selector] //检查事件来源时比较的对象
[,data] //传递的参数
,handler); //绑定的函数

/*表示当document触发了click事件,
检查这个事件是否由后代元素中的标签a所触发,
如果是,则执行handler函数*/

$(document).on("click","a",handler);
$(element).on("event",handler); //相当于$(element).bind("event",handler)

六、jQuery中的Ajax

jQuery封装的Ajax有三层:最底层的$.ajax()提供丰富的选项。第二层的load()$.get()$.post用于载入一个url的内容,与服务器交换数据,加载js脚本等。第三层的$.getJSON()getScript()用于加载指定类型的文件。

load()

1
2
3
4
load(url          //请求地址,地址中可以传入以空格隔开的filter用于选取返回的html中指定的内容
[,data] //发送至服务器的数据,没有则使用GET方式,有则使用POST方式
[,callback] //执行的回调函数,不管成功与否都会执行,回调有三个形参:responseText,status和XHR对象
);

get()和post()

get和post都是jQuery的全局函数,load是应用在jQuery对象上的。

1
2
3
4
5
get(url          //请求地址
[,data] //发送至服务器的数据,追加在url中
[,callback] //执行的回调函数,成功时执行,只有两个参数:返回的数据和状态
[,type] //指定服务端返回的格式
);

1
2
3
4
post(url          //请求地址,地址中可以传入以空格隔开的filter用于选取返回的html中指定的内容
[,data] //发送至服务器的数据,数据编码后存放在请求体中
[,callback] //执行的回调函数,成功时执行,只有两个参数:返回的数据和状态
);

$ajax()

该方法所需的参数选项以键值对的方式保存在对象中,详见