`
bencode
  • 浏览: 109613 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

jQuery源码解析2(Core)

    博客分类:
  • WEB
阅读更多

 在上一篇中,我们介绍了jQuery Utilities部分的代码。 这一部分要看看Core部分的。

 

我们知道 $('#id') 或 jQuery('#id') 将会返回一个对象, 这个对象的构造函数是:jQuery.fn.init

 

	jQuery = window.jQuery = window.$ = function( selector, context ) {
		return new jQuery.fn.init( selector, context );
	},

 

jQuery.fn.init.prototype = jQuery.fn;

 

让我们先看看 jQuery.fn.init

 

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		selector = selector || document;

 

selector 可以指定不同的数据类型,我们一个一个来:

 

1.  jQuery(element);  // an html dom element

 

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

 

 所以我们可以这样使用:

 

var elem = $(element); // 用于包装一个html dom元素, 以便使用jQuery操作它。

 

注意到以上代码,所以我们还可以像数组一样使用它:)

 

elem[0]; // return html dom element

elem.length; //

 

 

2. jQuery(html, [context]),  jQuery(elements, [context])

 

 

		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			var match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] )
					selector = jQuery.clean( [ match[1] ], context );

 

quickExpr 是一个正则式,用于匹配一个html string 或 id 字符串 (见第1篇)

 

以上部分处理这样的调用:

 

$('<div id="new-div" />')   

 

稍微浏览一下jQuery.clean, 知道它解析字符串,返回 html dom 元素的数组。 

 

解析之后, selector 是一个 html dom 元素的数组。

 

然后: 

 

		return this.setArray(jQuery.isArray( selector ) ?
			selector :
			jQuery.makeArray(selector));

 

// setArray 马上就会分析到(因为下面用到)

 

jQuery(elements, [context])

 

这个直接调用上面的setArray。

 

 

3. jQuery('#id')

 

如果是id字符串

 

 

				// HANDLE: $("#id")
				else {
					var elem = document.getElementById( match[3] );

					// Handle the case where IE and Opera return items
					// by name instead of ID
					if ( elem && elem.id != match[3] )
						return jQuery().find( selector );

					// Otherwise, we inject the element directly into the jQuery object
					var ret = jQuery( elem || [] );
					ret.context = document;
					ret.selector = selector;
					return ret;
				}

 

除去 IE 的 hack 部分

 

$('#id') 相当于:

 

var dom = document.getElementById('#id');

var elm = $(dom);
elm.context = document;
elm.selector = '#id'';

 

所以,使用 $('#id') 是非常快的,因为它直接调用 document.getElement 取得元素,不需要额外的解析。

 

//---

 

4. jQuery(callback);

 

 

			} else if ( jQuery.isFunction( selector ) )
				return jQuery( document ).ready( selector );

 

 

// 以下三个看喜欢选用。

$(function() {...}) ;

$(document).ready(function() {...}); 

$().ready(function() {...});

 

 

5. jQuery(css_selector, [context]); 

 

 

		if ( typeof selector === "string" ) {
			var match = quickExpr.exec( selector );
			if ( match && (match[1] || !context) ) {
				...
			} else
				return jQuery( context ).find( selector );

 

如果是除id 以外的 css 选择器, 那么就把这个艰巨任务的任务交给 

 

 jQuery( context ).find( selector );


 

6.  jQuery(jq)

 

		if ( selector.selector && selector.context ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return this.setArray(jQuery.isArray( selector ) ?
			selector :
			jQuery.makeArray(selector));

 

有时候我们这样:

 

var a = $('#id');

...

...

在某一个地方

$(a).click(...) 

 

就是重复包装了一个jquery对象(有时候忘记了,是一个jq对象还是一个html dom)。

这个速度也挺快的,因为只是进行简单的引用赋值。

 

---

setArray很简单:

 

 

	setArray: function( elems ) {
		this.length = 0;
		Array.prototype.push.apply( this, elems );
		return this;
	}

 

所以我们可以像使用数组一样引用jQuery中的dom元素

 

分析了 jQuery 的构造函数,下面看一些API 文档 Core 部分的方法。

 

先看 jQuery Object Accessors 部分

 

1. each(callback)

 

	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

 

args 内部使用。

 

2. size()

 

	size: function() {
		return this.length;
	},

 

3. length, selector, context

 

构造函数中已分析过

 

4. eq(i)

 

 

	eq: function( i ) {
		return this.slice( i, +i + 1 );
	},

 

 

+i, 就是 0+i, 常用于转成整形(如 +new Date())

 

假设我们有这样的html

<div class="mydiv" /> 
<div class="mydiv" /> 
<div iclass="mydiv" /> 
<div class="mydiv" /> 

<div class="mydiv" /> 

 

我们要对第3个节点进行操作,可以这样:

 

$('.mydiv').eq(3).css(...

 

5. get(), get(index)

 

 

	get: function( num ) {
		return num === undefined ?
			Array.prototype.slice.call( this ) :
			this[ num ];
	},

 

 

代码已直观到超出我的解释能力了。

 

6. index(elem)

 

 

	index: function( elem ) {
		return jQuery.inArray(
			elem && elem.jquery ? elem[0] : elem
		, this );
	},

 

 

inArray返回的是位置,见第1篇

 

index的参数也可以是 jQuery 对象哦

 

 

再看 Data 部分

 

首先来看看一个内部方法 jQuery.data

 

 

function now(){
	return +new Date;
}

 

 

 

var expando = "jQuery" + now(), uuid = 0, windowData = {};

 

 

一个函数,几个变量,我们 go on!

 

jQuery.data 将一个对象和一个 html dom关联。 让我们可以管理节点相关数据。

 

见API文档:http://docs.jquery.com/Internals 

 

 

 

 

jQuery.extend({
	cache: {},  // 实际的数据存放在这里

	data: function( elem, name, data ) {
		elem = elem == window ? // 对 window 进行特殊处理(在IE下 document == window)
			windowData :
			elem;

		var id = elem[ expando ];  // 节点上其实仅仅存一个uuid, expando 是一个串
		if ( !id )
			id = elem[ expando ] = ++uuid;  // 节点没有uuid, 就生成一个

		if ( name && !jQuery.cache[ id ] )
			jQuery.cache[ id ] = {};	// 节点相关的数据保存在这里

		if ( data !== undefined )
			jQuery.cache[ id ][ name ] = data;	// 存数据

		return name ? 
			jQuery.cache[ id ][ name ] :	// 取数据
			id;	// 取ID
	},

 

 

所以可以以下几种方式使用(在jQuery内部使用)

 

var id = jQuery.data(elm); // 取 uuid,

var value = jQuery.data(elm, name);

var value = jQuery.data(elm, name, value);

 

//---

再看 removeData

 

 

	removeData: function( elem, name ) {
		elem = elem == window ?	// 如上
			windowData :
			elem;

		var id = elem[ expando ];

		if ( name ) {	// 仅仅移除name相关的数据
			if ( jQuery.cache[ id ] ) {
				delete jQuery.cache[ id ][ name ];

				// 如果 jQuery.cache[id] 是空对象,那么就 jQuery.removeData(elem)
				name = "";

				for ( name in jQuery.cache[ id ] )
					break;

				if ( !name )
					jQuery.removeData( elem );
			}
		} else {	// 移除节点的关联数据
			// 先删除dom 节点上的 uuid
			try {
				delete elem[ expando ];
			} catch(e){
				// IE下需要使用removeAttribute进行移除
				if ( elem.removeAttribute )
					elem.removeAttribute( expando );
			}
			// 再删除实际数据
			delete jQuery.cache[ id ];
		}
	},

 

所以可以这样使用(jQuery内部)

 

jQuery.removeData(elem);

jQuery.removeData(elem, name);

 

好了,下面就看看我们经常使用的 data 吧

 

 

1. data(name), data(name, value)

 

 

jQuery.fn.extend({
	data: function( key, value ){
		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			if ( data === undefined && this.length )
				data = jQuery.data( this[0], key );

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;
		} else
			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
				jQuery.data( this, key, value );
			});
	},

 

 

代码很简单,可是应用却让人有点遐想(是否想到了数据绑定?

 

稍微整理一下先:


$(elem).data('abc.def') :


 triggerHandler('getData.def!', ['abc']) ---> jQuery.data(elem, 'abc.def') --> jQuery.data(elem, 'abc')

 

只作用于第一个元素

 

 

$(elem).data('abc.def', 'hello world!'):


(1)  trigger('setData.def!', ['abc', 'hello world']) 
(2)  jQuery.data(elem, 'abc.def', 'hello world');

 

作用于jQuery对象中的所有元素

 

 

//---看一个例子:

 

 

页面上有一个HTML输入域, 它可以弄入tags

 

 

<input id="tags" type="text" />

 


我们在某个地方这样初始化这个输入域, 它应该按照一定的格式显示tags:

	var tags = ['Javascript', 'jQuery', 'Web前端'];
	$('#tags').data('tags', tags);
 
我们可以这样获取tags:

var tags = $('#tags').data('tags');
 

如何从输入域显示和获取tags, 在最接近输入域的地方有这样的代码:


 

	$('#tags').bind('getData', function(e, name) {
		if (name == 'tags') {
			return $(this).val().split(/\s*;\s*/);
		}
	}).bind('setData', function(e, name, value) {
		if (name == 'tags') {
			$(this).val(value.join('; '));
		}
	});

 

//~ 

 

 2. queue(name), queue(name, callback), queue(name, queue)

 

同样,有我们不好使用,但依然存在的 

jQuery.queue,  jQuery.dequeue

 

 我们可以用它实现Chain of Responsibility 或Active Objects 模式,让我们可以把操作串起来。

 

jQuery.extend({
	...


	queue: function( elem, type, data ) {
		if ( elem ){
			type = (type || "fx") + "queue";

			var q = jQuery.data( elem, type );
	
			if ( !q || jQuery.isArray(data) )
				q = jQuery.data( elem, type, jQuery.makeArray(data) );
			else if( data )
				q.push( data );
	
		}
		return q;
	},

 

(PS: return q 在 if 里面更好?)
 

1. type 默认为 'fx' <-- Effects 将使用此queue

2. data 如果为 array, 则替换原 queue (用makeArray, 是需要创建一个新数组,因为dequeue会修改数组。)

 

下面看degueue:

 

	dequeue: function( elem, type ){
		var queue = jQuery.queue( elem, type ),
			fn = queue.shift();
		
		if( !type || type === "fx" )
			fn = queue[0];
			
		if( fn !== undefined )
			fn.call(elem);
	}

 

代码很简单: 取出第一个操作, 执行它。 (或者说: 执行下一个操作,更恰当些)。

 

 

jQuery.queue 和 jQuery.dequeue 是工具方法, jQuery对象对它们进行了包装,让我们可以使用:

 

jQuery.fn.extend({
	...

	queue: function(type, data){
		if ( typeof type !== "string" ) { 
			data = type;
			type = "fx";
		}

		if ( data === undefined )
			return jQuery.queue( this[0], type );

		return this.each(function(){
			var queue = jQuery.queue( this, type, data );
			
			 if( type == "fx" && queue.length == 1 )
				queue[0].call(this);
		});
	},

 

1.  $('#id').queue(function() ...);   相当于   $('#id').queue('fx', function() ...);   用于添加操作到 fx

2.  $('#id').queue() ;  相当于 $('#id').queue('fx') ; 

 

 

dequeue 很简单, 对每个dom元素, 都调用jQuery.dequeue

 

	dequeue: function(type){
		return this.each(function(){
			jQuery.dequeue( this, type );
		});
	}

 

在API文档中有可运行的demo,可以结合看看。

 

同样,还是总结一下:

 




 
 

 

 

 

  • 大小: 16.4 KB
分享到:
评论
4 楼 zachary.guo 2010-09-19  
这幅 uml 图是用什么工具画的?
3 楼 yuyue007 2010-09-03  
初学者收益了
2 楼 oolala 2010-07-24  
好文章,需要仔细读一下。
1 楼 matychen 2010-03-10  
收下,慢慢看!

相关推荐

    jquery源码 带格式

    ### jQuery源码解析:深入理解jQuery JavaScript库 #### 核心概述 `jQuery JavaScript Library v1.8.3`是jQuery框架的一个版本,发布于2012年11月13日,由jQuery Foundation和其他贡献者共同开发,遵循MIT许可协议...

    jquery源码好不容易找到的与大家分享

    《jQuery源码解析:深入理解核心机制》 jQuery,这个小巧而强大的JavaScript库,自2006年发布以来,就以其简洁的API和出色的跨浏览器兼容性赢得了开发者们的广泛喜爱。今天,我们有幸深入剖析这份来之不易的jQuery...

    jquery-1.11源码

    《深入解析jQuery 1.11源码》 jQuery,作为JavaScript库的杰出代表,以其简洁易用的API,极大地简化了DOM操作、事件处理、动画制作和Ajax交互。...对jQuery源码的探索,是提升JavaScript开发能力的重要步骤。

    jquery源码和API

    二、jQuery源码解析 jQuery的源码组织结构清晰,分为核心(core)、选择器(selector)、DOM操作(manipulation)、事件(events)、遍历(traversing)、效果(effects)等多个模块。源码中大量使用了闭包和原型链...

    jQuery API 详解 中文版

    《jQuery API 详解 中文版》是一份详尽解析jQuery库核心功能的文档,涵盖了从基础到高级的各种操作。这份资料共分为八大部分,包括Core(核心)、DOM(文档对象模型)、CSS(样式)、JavaScript(脚本语言)、...

    jquery UI 1.7源代码

    2. `ui`目录包含了jQuery UI的所有组件和功能的JavaScript源码。例如,`ui.core.js`是基础组件,提供了事件处理和其他通用功能;`ui.widget.js`是所有组件的基类;`ui.datepicker.js`则是日期选择器的实现。通过阅读...

    jQuery json+struts2 jar包全集

    这些jar包的集成意味着我们可以利用jQuery在前端进行用户交互和数据展示,通过Ajax发送JSON格式的请求到后端的Struts2应用,Struts2接收请求,处理业务逻辑,并以JSON格式返回结果,最后jQuery再次解析这些数据并...

    jquery:jquery源码分析

    **jQuery: 深入解析源码** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了 JavaScript 的 DOM 操作、事件处理和动画制作。本文将深入探讨 jQuery 的源码,帮助开发者理解其内部机制,从而更好地利用这个...

    HeadFirst jquery源代码

    8. **版本迭代**:jQuery经历了多个版本的迭代,从最初的1.x到后来的2.x和3.x,优化性能,支持现代浏览器特性,并引入了模块化设计(如jQuery UI和jQuery Core)。 9. **jQuery与现代前端框架**:随着React、Vue和...

    带锋利的JQuery第二版的源码

    《带锋利的jQuery第二版》是一本深入探讨jQuery库的书籍,其源码提供了学习和研究jQuery核心机制的重要资源。这本书旨在帮助开发者理解和掌握jQuery...总之,掌握jQuery源码对于前端开发者来说,是一项极具价值的投资。

    jQuery:jQuery 源码分析

    3. **Core**:jQuery 对象的核心,包括链式调用、遍历、类型检测等功能。 4. **Traversing**:提供遍历和过滤 DOM 树的方法。 5. **Manipulation**:处理 DOM 元素,如创建、插入和删除。 6. **Ajax**:实现异步数据...

    jquery 跨iframe拖拽

    2. **设置拖拽元素**:在主页面或者IFrame中的某个元素(比如一个div)上,我们需要应用`.draggable()`方法,定义拖动行为。例如: ```javascript $('#draggableElement').draggable(); ``` 这将使`#...

    jquery.jqplot图表源码

    **jQuery.jqPlot图表源码详解** jQuery.jqPlot是一款基于JavaScript的开源图表库,它提供了丰富的图表类型,包括折线图、柱状图、饼图、散点图等,适用于网页上的数据可视化。该库设计简洁,易于使用,允许开发者...

    jquery.jqGrid源码.zip

    《jQuery.jqGrid源码深度解析》 jQuery.jqGrid是一款功能强大的JavaScript表格插件,它基于jQuery库,用于创建动态、交互式的网格视图。本篇文章将深入探讨jqGrid的源码,揭示其内部机制,帮助开发者更好地理解和...

    jqueryUI(jquery演示部分)

    **jQuery UI 深度解析** jQuery UI 是一个基于 jQuery 库的强大且功能丰富的前端开发框架,它提供了许多用户界面组件,如对话框、滑块、日历、拖放等功能,帮助开发者创建交互性强、用户体验良好的Web应用。在这个...

    jquery ui 1.8.2 code

    `js` 文件夹存放 JavaScript 文件,其中 `ui/jquery.ui.core.js` 是核心模块,其他如 `ui/jquery.ui.widget.js`、`ui/jquery.ui.mouse.js` 等则为各个组件的具体实现;`css` 文件夹包含样式表,用于定义组件的视觉...

    jquery-1.10.1.zip_JavaScript/JQuery_JavaScript_

    三、jQuery 1.10.1源码解析 1. **模块化设计**:jQuery采用了模块化设计,源码中可以看到`core.js`、`selector.js`等独立模块,每个模块负责特定功能。 2. **链式调用**:jQuery的返回对象是一个jQuery实例,每次...

    jquery-ui-1.8.18.custom.zip

    2. **development-bundle**:这个目录包含了 jQuery UI 的源码,包括未压缩和未合并的 JavaScript 和 CSS 文件,方便开发者调试和定制。 - **js** 子目录:存放未压缩的 JavaScript 文件,如 "ui/jquery.ui.core....

    ztree 源码和例子

    ZTree是一款基于jQuery的灵活可配置的树形插件,广泛应用于网页界面中的树形菜单、数据展示和管理。在这个名为“ztree 源码和例子”的压缩包中,包含的是ZTree的v3.5.17版本的源代码以及相关的示例,这对于开发者来...

Global site tag (gtag.js) - Google Analytics