开始:
jQuery在JavaScript中的本质是一个自定义对象。
只不过这个自定义的对象强大的过分,可以代替原生JavaScript做大部分的事,如:获取DOM元素、操作DOM、绑定事件、实现动画、Ajax操作等等。
jQuery与原生JavaScript最重要,最强大,也最让人欢喜开心的重大差别是jQuery对象里的大量方法不用像原生JavaScript里的方法那样,时时刻刻要考虑浏览器之间的兼容性。
因为jQuery对象已经帮我们解决了各大浏览器之间的大部分兼容性问题,因此使用jQuery进行DOM编程等基本上是不需要考虑兼容性问题。
除了这个最重要的差别,jQuery对象封装好的方法是非常简洁和优雅的,所以使用jQuery可以快速、并且高效的进行各种功能的设计。
DOM编程的基本过程是什么?
1. 获取DOM元素。
可以说这一步是所有DOM编程的入口。因为基本上所有的DOM操作都是针对一个或者一组DOM元素的,所以获取到即将要进行编程的DOM元素是DOM编程的第一步。
2. 操作DOM元素。
每个DOM元素都是一个对象,拥有自己的属性和方法,并且和周围的其他DOM元素有着这样或那样的关系。而DOM编程便是以这个为基础实现各种各样的效果。
正如图中所示,利用jQuery进行DOM编程和直接应用原生JavaScript进行编程的基本过程差不多。
其中的入口模块便是DOM编程第一步 获取DOM元素 ,也是本篇文章的主题。
和在原生JavaScript中获取某个或某类DOM元素的复杂和散乱不同。
jQuery获取DOM元素是非简单和统一的。
在jQuery中,选取任何DOM元素都只需要使用一个方法:jQuery();
是的,不用像在原生JavaScript中:
选取带有id属性的元素使用document.getElementById(“id”)
选择带有类属性的元素使用另一个方法:document.getElementsByClass(“class”)
选取符合某个CSS选择器的元素,或者根据元素名和name属性选取元素又要使用另一个方法。
jQuery利用面向对象编程中“封装”这个伟大的特性,将冗长的、散乱的代码都封装在了一起。
jQuery():
可以接受很多种参数:字符串、DOM对象、jQuery对象、原生JavaScript对象、函数等等。
根据传入的对象不同,jQuery()可以做出不同的反应。
在正式说jQuery()可以接受传入的参数之前,先来看看一段jQuery的源代码,这将有助于理解jQuery()的工作原理。
(注意:这部分不想看的也可以跳过,不影响理解)
;(function(window){
//入口模块开始
var jQuery=(function(){
//jQuery构造函数
var jQuery=function(selector,context){
return new jQuery.fn.init(selector,context,rootjQuery);
};
//在jQuery的原型中定义方法,以方便jQuery对象继承。
jQuery.fn=JQuery.prototype={
init : function(selector,context,rootjQuery){
//函数体
};
};
//将jQuery.fn.init的原型对象用jQuery.fn覆盖掉。
jQuery.fn.init.prototype=jQuery.fn;
//最后将这个包含jQuery.fn.init示例的jQuery返回到上一层。
return jQuery;
})();
//入口模块结束
//将jQuery作为全局变量暴露给外界,作为唯一的接口。
window.jQuery=jQuery=$;
})(window);
这段是超级简化后的jQuery底层代码。
可以看到,所有的jQuery代码都是包含在一个闭包里的,只暴露了一个接口给外界。
而这个接口正好就是入口模块的jQuery()方法,所以在很多jQuery文档中说所有的jQuery功能都是基于这个方法的原因就在这里。
可能已经有人发现其中有一段代码很奇特,就是下面这段。
var jQuery=function(selector,context){
return new jQuery.fn.init(selector,context,rootjQuery);
}
是的,正如亲眼所见,使用jQuery()选择元素后返回的对象实例其实是jQuery.fn.init()构造函数的实例。
那么为什么jQuery.fn.init()的实例可以使用jQuery原型中方法呢?
这源于下面这段代码:
jQuery.fn.init.prototype=jQuery.fn;
jQuery.fn.init的原型对象被jQuery的原型对象覆盖了。
这段代码总的来说就是,调用jQuery()其实就是调用了jQuery.fn.init()方法,给jQuery(selector)传参数,其实最后传给了jQuery.fn.init(selector),最后返回jQuery.fn.init()构造函数的实例作为jQuery()的返回值,并且由于jQuery.fn.init()的原型已经被jQuery的原型所覆盖,所以实际上jQuery.fn.init()的实例和jQuery的实例从本质上来说没什么差别。
并且这样做的好处就是省去了new操作符:本来如果利用构造函数jQuery()来创建jQuery对象是需要new操作符的,但现在交给了另一个构造函数jQuery.fn.init()来创建,所以jQuery()实际上只是一个普通函数,这个普通函数的返回值是jQuery.fn.init()的实例,而这个实例可以当做jQuery对象来使用,因为原型被覆盖。
所以jQuery()这个函数对象包含的值严格意义上来说应该是jQuery.fn.init(selector)返回的实例。
知道了jQuery对象的来源,那么就应该知道调用jQuery()其实就是调用了jQuery.fn.init()方法,所以所有的判断逻辑都应该是定义在jQuery.fn.init()中的,接来就是分析jQuery.fn.init()在接到各种类型的参数后怎么进行逻辑判断,并给出相应的返回值。
先来看一张图。
从图中可以看出,jQuery()有7种之多的用法。
其中:
1.jQuery( selector [, context] )
2.jQuery(callback)
3.jQuery( html [ , ownerDocument ] )
4.jQuery(DOM元素)
这四种方式的应用比较广泛。
1.jQuery( selector [, context ] ) (选择模式)
当传入的参数selector是一个字符串,且该字符串是一个选择器表达式时,则jQuery进入选择模式。
jQuery()的这种选择模式可以接受一个或两个参数。
1.当传入的选择器表达式是一个简单的#id,且没有指定选择上下文(context)时,则jQuery()调用JavaScript的原生方法:document.getElementById(“#id”),在整个文档树中查找属性值id为指定值的元素,并返回。
2.当传入的选择器表达式是一个复杂的选择器字符串,如:“div span”,或者指定了选择上下文context时,则调用jQuery方法的.find()来在整个文档树,或者指定的上下文中查找元素,并返回。
注意:.find()方法又会调用jQuery的选择器引擎Sizzle来查找元素。
所以,$("span",$("div"))
实际上可以写成:$("div").find("span")
。
下面举一个在事件处理程序中应用context选择上文的例子
$("div").click(function(){
$("span",this).addClass("abc");
//$("span",this)这段代码的意思就是在当前元素下查找span元素。
})
小结:
1.jQuery( selector [, context ] ) 是入口函数jQuery()七种用法中最常用的一种,没有之一,我将这个用法称为选择模式
2.jQuery( selector [, context ] )可以接受一个或者两个参数,一个是选择器表达式,另一个是查找上下文。
3.当选择器表达式是简单的id值,且没有指定选择上下文时,则调用原生的查找方法来查找。当选择器表达式是复杂的选择器时,则调用.find()方法来查找。
4.context选择上下文可以是DOM元素,也可以是jQuery对象,但最终都会被转化为jQuery对象,然后调用.find()方法来查找元素。
5.选择模式传入的selector是字符串,且该字符串是选择器表达式时触发的模式。除此之外,当selector是字符串,可是该字符串是html代码时,则触发创造模式。
2. jQuery( html [, ownerDocument ] ) || jQuery( html , props ) 创造模式
当传入的参数是一个字符串,且该字符串是一个HTML代码的时候,则jQuery()触发创造模式
1.如果传入的字符串HTML代码是一个单独的标签,如:$("<div>")
、 $("<img/>")
,则jQuery将调用JavaScript原生方法:document.createElement()来创建一个DOM元素,并用jQuery对象包装该DOM元素后返回。
注意:当HTML代码是单独的标签,也就是代表着创建的DOM元素还没有任何自定义的属性时,可以使用创造模式中的 jQuery( html , props )来给创建出来的DOM元素添加各种各样的属性,甚至添加事件、样式等等。
举个栗子
$("<div>",{
"class" : "abc",
click : function(){
alert("00")
},
id : "abc",
css : {
height : "1000px",
width : "500px",
},
text : "nihao",
})
正如代码所示, jQuery( html , props ) 中的参数html代码一定要是单独标签,如果是复杂标签则会报错。并且参数props是一个对象,其中可以包含以下特殊属性:val、css、html、text、data、width、height、offset,设置这些特殊值的时候,相应的jQuery方法就会被执行,.val()、css()、html()、text()、data()、width()、height()、offset()。
创造模式中的这个方法可以很方便的给一个单独标签添加大量的属性。
2.如果传入的字符串参数HTML代码是除单独标签之外的复杂标签代码,
如:$("<div id="abc"> <span>你好,我是复杂标签</span> </div>")
则jQuery将利用浏览器的innerHTML机制创建DOM元素。这个过程又由方法jQuery.buildFragment()和方法jQuery.clean()实现。
在 jQuery( html [, ownerDocument ] )中的第二个参数 ownerDocument用于指定创建新DOM元素的文档对象,如果没有指定,则认为是当前文档对象。
小结:
- 如果传入jQuery()的参数是字符串,且字符串是HTML代码的时候触发创造模式。
- 如果传入的HTML代码是单独标签,则jQuery会调用JavaScript原生方法:document.createElement(),来创建一个新的DOM元素,并且还可以使用 jQuery( html , props )方法,其中props参数为对象,其属性值设置的是被创建的DOM元素的属性值。
- 如果传入的HTML代码时复杂标签,则jQuery将利用浏览器的innerHTML机制创建DOM元素。这个过程又由方法jQuery.buildFragment()和方法jQuery.clean()实现。
- 使用jQuery(),创建复杂标签的时候,记得注意单双引号的问题。
3. jQuery( element ) || jQuery( elementArray ) 包装模式
当传入的参数是DOM元素时,则触发包装模式。
包装模式主要是将传进来的DOM元素,或者DOM元素数组用jQuery对象包装之后,返回一个jQuery对象。
这样做的目的通常是为了让DOM元素也能使用jQuery封装好的方法。
这种用法通常出现在事件监听函数中的:$(this),将当前的DOM元素封装成jQuery元素。
4. jQuery(callback)
如果传入的参数是一个函数, 则在document上绑定一个ready事件监听函数。这种用法是$(document).ready(function(){ })
的简写。ready事件当DOM结构加载完成时触发,所以ready事件触发时间早于load事件。
5.jQuery(object)
如果传入一个普通的JavaScript对象,则把该JavaScript封装到jQuery对象中并返回。
6.jQuery()
返回一个空的jQuery对象。
最终总结:
- jQuery最被人们津津乐道的一部分就是它的选择功能,利用它自己编写的选择器,完全可以选择到DOM树中的任何元素。
- jQuery()作为入口模块,是jQuery整个体系中最基础的一部分,jQuery中所有的方法都要在jQuery对象上执行。
- jQuery()的用法足有7种之多,但最常用的大约有四种。
- 理解好jQuery()是进军jQuery的第一步。