博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JQuery 原理
阅读量:6946 次
发布时间:2019-06-27

本文共 17803 字,大约阅读时间需要 59 分钟。

jQuery 的原型关系图

 

黄色的为对象,蓝色的为函数。

 

一、核心部分

 

 

核心部分实现了两种选择器,使用 id 和标记名,还可以提供 css 的设置,以及 text 的设置。

 

  1 
//
 # 表示在 jQuery 1.4.2 中对应的行数
  2 
  3 
//
 定义变量 undefined 方便使用
  4 
var
 undefined 
=
 undefined;
  5 
  6 
//
 jQuery 是一个函数,其实调用 jQuery.fn.init 创建对象
  7 
var
 $ 
=
 jQuery 
=
 window.$ 
=
 window.jQuery               
//
 #19
  8 
            
=
 
function
 (selector, context) {
  9 
                
return
 
new
 jQuery.fn.init(selector, context);
 10 
            },
 11 
 12 
//
 定义 toString 变量引用 Object 原型的 toString
 13 
toString 
=
 Object.prototype.toString,
 14 
 15 
//
 用来检查是否是一个 id
 16 
idExpr 
=
 
/
^#([\w-]+)$
/
;
 17 
 18 
//
 设置 jQuery 的原型对象, 用于所有 jQuery 对象共享
 19 
jQuery.fn 
=
 jQuery.prototype 
=
 {                        
//
 #74
 20 
 21 
    length: 
0
,                                          
//
 #190
 22 
 23 
    jquery: 
"
1.4.2
"
,                                    
//
 # 187
 24 
 25 
    
//
 这是一个示例,仅仅提供两种选择方式:id 和标记名
 26 
    init: 
function
 (selector, context) {                
//
 #75
 27 
 28 
        
//
 Handle HTML strings
 29 
        
if
 (
typeof
 selector 
===
 
"
string
"
) {
 30 
            
//
 Are we dealing with HTML string or an ID?
 31 
            match 
=
 idExpr.exec(selector);
 32 
 33 
            
//
 Verify a match, and that no context was specified for #id
 34 
            
if
 (match 
&&
 match[
1
]) {
 35 
                
var
 elem 
=
 document.getElementById(match[
1
]);
 36 
                
if
 (elem) {
 37 
                    
this
.length 
=
 
1
;
 38 
                    
this
[
0
=
 elem;
 39 
                }
 40 
            }
 41 
            
else
 {
 42 
                
//
 直接使用标记名
 43 
                
var
 nodes 
=
 document.getElementsByTagName(selector);
 44 
                
for
 (
var
 l 
=
 nodes.length, j 
=
 
0
; j 
<
 l; j
++
) {
 45 
                    
this
[j] 
=
 nodes[j];
 46 
                }
 47 
                
this
.length 
=
 nodes.length;
 48 
            }
 49 
 50 
            
this
.context 
=
 document;
 51 
            
this
.selector 
=
 selector;
 52 
 53 
            
return
 
this
;
 54 
        }
 55 
    },
 56 
 57 
    
//
 代表的 DOM 对象的个数
 58 
    size: 
function
 () {                                 
//
 #193
 59 
        
return
 
this
.length;
 60 
    },
 61 
 62 
    
//
 用来设置 css 样式
 63 
    css: 
function
 (name, value) {                       
//
 #4564
 64 
        
this
.each(
 65 
                    
function
 (name, value) {
 66 
                        
this
.style[name] 
=
 value;
 67 
                    },
 68 
                    arguments       
//
 实际的参数以数组的形式传递
 69 
                    );
 70 
        
return
 
this
;
 71 
    },
 72 
 73 
    
//
 用来设置文本内容
 74 
    text: 
function
 (val) {                              
//
 #3995
 75 
        
if
 (val) {
 76 
            
this
.each(
function
 () {
 77 
                
this
.innerHTML 
=
 val;
 78 
            },
 79 
                    arguments       
//
 实际的参数以数组的形式传递
 80 
                    )
 81 
        }
 82 
        
return
 
this
;
 83 
    },
 84 
 85 
    
//
 用来对所有的 DOM 对象进行操作
 86 
    
//
 callback 自定义的回调函数
 87 
    
//
 args 自定义的参数
 88 
    each: 
function
 (callback, args) {                   
//
 #244
 89 
        
return
 jQuery.each(
this
, callback, args);
 90 
    }
 91 
 92 
}
 93 
 94 
//
 init 函数的原型也就是 jQuery 的原型
 95 
jQuery.fn.init.prototype 
=
 jQuery.prototype;            
//
 #303
 96 
 97 
//
 用来遍历 jQuery 对象中包含的元素
 98 
jQuery.each 
=
 
function
 (object, callback, args) {       
//
 #550
 99 
100 
    
var
 i 
=
 
0
, length 
=
 object.length;
101 
102 
    
//
 没有提供参数
103 
    
if
 (args 
===
 undefined) {
104 
105 
        
for
 (
var
 value 
=
 object[
0
];
106 
                    i 
<
 length 
&&
 callback.call(value, i, value) 
!==
 
false
;
107 
                     value 
=
 object[
++
i])
108 
        { }
109 
    }
110 
111 
    
else
 {
112 
        
for
 (; i 
<
 length; ) {
113 
            
if
 (callback.apply(object[i
++
], args) 
===
 
false
) {
114 
                
break
;
115 
            }
116 
        }
117 
    }
118 
}
119 

在 jQuery 中, jQuery 对象实际上是一个仿数组的对象,代表通过选择器得到的所有 DOM 对象的集合,它像数组一样有 length 属性,表示代表的 DOM 对象的个数,还可以通过下标进行遍历。

 

95 行的 jQuery.each 是 jQuery 中用来遍历这个仿数组,对其中的每个元素进行遍历处理的基本方法,callback 表示处理这个 DOM 对象的函数。通常情况下,我们并不使用这个方法,而是使用 jQuery 对象的 each 方法进行遍历。jQuery 对象的 css 和 text 方法在内部实际上使用 jQuery 对象的 each 方法对所选择的元素进行处理。

 

二、数据部分

 

在 jQuery 中,可以对每一个 DOM 对象保存私有的数据。

 

这个数据当然要通过属性来进行存取,但是,有多个属性怎么办呢?,要定义多个属性吗?,属性的名字叫什么呢?会不会与其他的属性有冲突呢?

 

在 jQuery 中,针对 DOM  对象扩展的私有数据可以用一个对象来表示,多个数据就使用这个对象的多个属性来表示。为了能够通过 DOM 对象找到这个扩展数据对象,而不会与其他现有的属性冲突,在 jQuery 中通过 expando 这个常量表示扩展对象的属性名,这个 expando 的值是计算出来的。而这个属性的值就是用来找到扩展对象的键值。

 

例如,我们可以定义 expando 的值为 "jQuery1234" ,那么,我们可以为每个 DOM 对象增加这个名为  "jQuery1234" 的属性,这个属性的值可以是一个键,例如为 1000。

 

在 jQuery 对象上的 cache 用来保存所有对象扩展的对象,这个对象可以看作一个字典,属性名就是键值,所对应的值就是扩展数据对象。

 

也就是说,在 jQuery 对象的 cache 上,将会有一个 1000 的成员,这个成员引用的对象就是 1000 号 DOM 对象的私有扩展对象。1000 号成员的私有数据将被存在在这个对象上。

 

当一个 DOM 对象需要取得扩展数据的时候,首先通过对象的 expando 属性取得一个键值,然后通过这个键值到 jQuery.cache 中取得自己的扩展对象,然后在扩展对象上读写数据。

 

  1 
//
/ <reference path="jQuery-core.js" />
  2 
  3 
//
 常用方法
  4 
function
 now() {
  5 
    
return
 (
new
 Date).getTime();
  6 
}
  7 
  8 
//
 扩充数据的属性名,动态生成,避免与已有的属性冲突
  9 
var
 expando 
=
 
"
jQuery
"
 
+
 now(), uuid 
=
 
0
, windowData 
=
 {};
 10 
jQuery.cache 
=
 {};
 11 
jQuery.expando 
=
 expando;
 12 
 13 
//
 数据管理,可以针对 DOM 对象保存私有的数据,可以读取保存的数据
 14 
jQuery.fn.data 
=
 
function
 (key, value) {
 15 
 16 
    
//
 读取
 17 
    
if
 (value 
===
 undefined) {
 18 
        
return
 jQuery.data(
this
[
0
], key);
 19 
    }
 20 
    
else
 {  
//
 设置
 21 
 22 
        
this
.each(
 23 
                    
function
 () {
 24 
                        jQuery.data(
this
, key, value);
 25 
                    }
 26 
                    );
 27 
    }
 28 
}
 29 
//
 移除数据,删除保存在对象上的数据
 30 
jQuery.fn.removeData 
=
 
function
 (key) {
 31 
    
return
 
this
.each(
function
 () {
 32 
        jQuery.removeData(
this
, key);
 33 
    })
 34 
}
 35 
 36 
 37 
//
 为元素保存数据
 38 
jQuery.data 
=
 
function
 (elem, name, data) {     
//
 #1001
 39 
 40 
    
//
 取得元素保存数据的键值
 41 
    
var
 id 
=
 elem[expando], cache 
=
 jQuery.cache, thisCache;
 42 
 43 
    
//
 没有 id 的情况下,无法取值
 44 
    
if
 (
!
id 
&&
 
typeof
 name 
===
 
"
string
"
 
&&
 data 
===
 undefined) {
 45 
        
return
 
null
;
 46 
    }
 47 
 48 
    
//
 Compute a unique ID for the element
 49 
    
//
 为元素计算一个唯一的键值
 50 
    
if
 (
!
id) {
 51 
        id 
=
 
++
uuid;
 52 
    }
 53 
 54 
    
//
 如果没有保存过
 55 
    
if
 (
!
cache[id]) {
 56 
        elem[expando] 
=
 id;     
//
 在元素上保存键值
 57 
        cache[id] 
=
 {};         
//
 在 cache 上创建一个对象保存元素对应的值
 58 
    }
 59 
 60 
    
//
 取得此元素的数据对象
 61 
    thisCache 
=
 cache[id];
 62 
 63 
    
//
 Prevent overriding the named cache with undefined values
 64 
    
//
 保存值
 65 
    
if
 (data 
!==
 undefined) {
 66 
        thisCache[name] 
=
 data;
 67 
    }
 68 
 69 
    
//
 返回对应的值
 70 
    
return
 
typeof
 name 
===
 
"
string
"
 
?
 thisCache[name] : thisCache;
 71 
 72 
}
 73 
 74 
//
 删除保存的数据
 75 
jQuery.removeData 
=
 
function
 (elem, name) {     
//
 #1042
 76 
 77 
    
var
 id 
=
 elem[expando], cache 
=
 jQuery.cache, thisCache 
=
 cache[id];
 78 
 79 
    
//
 If we want to remove a specific section of the element's data
 80 
    
if
 (name) {
 81 
        
if
 (thisCache) {
 82 
            
//
 Remove the section of cache data
 83 
            
delete
 thisCache[name];
 84 
 85 
            
//
 If we've removed all the data, remove the element's cache
 86 
            
if
 (jQuery.isEmptyObject(thisCache)) {
 87 
                jQuery.removeData(elem);
 88 
            }
 89 
        }
 90 
 91 
        
//
 Otherwise, we want to remove all of the element's data
 92 
    } 
else
 {
 93 
 94 
        
delete
 elem[jQuery.expando];
 95 
 96 
        
//
 Completely remove the data cache
 97 
        
delete
 cache[id];
 98 
    }
 99 
}
100 
101 
//
 检查对象是否是空的
102 
jQuery.isEmptyObject 
=
 
function
 (obj) {
103 
    
//
 遍历元素的属性,只有要属性就返回假,否则返回真
104 
    
for
 (
var
 name 
in
 obj) {
105 
        
return
 
false
;
106 
    }
107 
    
return
 
true
;
108 
109 
}
110 
111 
//
 toString 是 jQuery 中定义的一个变量 #68
112 
//
 hasOwnProperty                    #69
113 
114 
//
 检查是否是一个函数
115 
jQuery.isFunction 
=
 
function
 (obj) {
116 
    
return
 toString.call(obj) 
===
 
"
[object Function]
"
;
117 
}
118 
119 
//
 检查是否为一个数组
120 
jQuery.isArray 
=
 
function
( obj ) {
121 
        
return
 toString.call(obj) 
===
 
"
[object Array]
"
;
122 
    }
123 
124 
//
 是否是纯粹的 js 对象,而不是 DOM 对象,或者 window 对象
125 
jQuery.isPlainObject 
=
 
function
( obj ) {
126 
        
//
 Must be an Object.
127 
        
//
 Because of IE, we also have to check the presence of the constructor property.
128 
        
//
 Make sure that DOM nodes and window objects don't pass through, as well
129 
        
if
 ( 
!
obj 
||
 toString.call(obj) 
!==
 
"
[object Object]
"
 
||
 obj.nodeType 
||
 obj.setInterval ) {
130 
            
return
 
false
;
131 
        }
132 
        
133 
        
//
 Not own constructor property must be Object
134 
        
if
 ( obj.constructor
135 
            
&&
 
!
hasOwnProperty.call(obj, 
"
constructor
"
)
136 
            
&&
 
!
hasOwnProperty.call(obj.constructor.prototype, 
"
isPrototypeOf
"
) ) {
137 
            
return
 
false
;
138 
        }
139 
        
140 
        
//
 Own properties are enumerated firstly, so to speed up,
141 
        
//
 if last one is own, then all properties are own.
142 
    
143 
        
var
 key;
144 
        
for
 ( key 
in
 obj ) {}
145 
        
146 
        
return
 key 
===
 undefined 
||
 hasOwnProperty.call( obj, key );
147 
    }
148 

 

 

 

下面的脚本可以保存或者读取对象的扩展数据。

 

1 
//
 数据操作
2 
$(
"
#msg
"
).data(
"
name
"
"
Hello, world.
"
);
3 
alert($(
"
#msg
"
).data(
"
name
"
));
4 
$(
"
#msg
"
).removeData(
"
name
"
);
5 
alert($(
"
#msg
"
).data(
"
name
"
));

 

 

三、 事件处理

 

在 jQuery 中,实际注册的事件处理函数是一个匿名的闭包函数,这个函数最终都是通过调用 jQuery.event.handle 进行处理的。

 

在对象的私有扩展对象上,专门增加了一个名为 events 的事件管理对象,在这个对象上每种事件分别对应一个同名的属性,这个属性的值是一个数组,针对这个事件的处理程序依次压入这个数组中,构成一个事件处理的列表。自定义的事件处理函数即被压入这个列表中。

 

在事件触发的时候,通过注册的匿名函数来执行 jQuery.event.handle ,由于使用了闭包,所以在这个函数中的 this 就是事件源对象,通过这个事件源对象找到对象的私有扩展数据,然后在 events 中找到对应的事件处理程序列表,最后,依次执行。

 

 

  1 
//
/ <reference path="jQuery-core.js" />
  2 
//
 #2076
  3 
  4 
//
 用于生成事件处理函数的 id
  5 
jQuery.guid 
=
 
1
;
  6 
  7 
//
 jQuery 的事件对象
  8 
jQuery.event 
=
 {    
//
 # 1555
  9 
 10 
    
//
 为对象增加事件
 11 
    
//
 elem 增加事件的元素, type 事件的名称, handler 事件处理程序, data 事件相关的数据
 12 
    add: 
function
 (elem, type, handler, data) {
 13 
 14 
        
var
 handleObjIn, handleObj;
 15 
 16 
        
//
 确认函数有一个唯一的 ID
 17 
        
if
 (
!
handler.guid) {
 18 
            handler.guid 
=
 jQuery.guid
++
;
 19 
        }
 20 
 21 
        
//
 取得这个元素所对应的缓存数据对象
 22 
        
var
 elemData 
=
 jQuery.data(elem);
 23 
 24 
        
//
 取得元素对应的缓存对象上的事件对象和所有事件共用的处理程序
 25 
        
var
 events 
=
 elemData.events 
=
 elemData.events 
||
 {};
 26 
        
var
 eventHandle 
=
 elemData.handle;
 27 
 28 
        
//
 是否已经有事件处理函数 handle 只有一个,都是使用 jQuery.event.handle
 29 
        
//
 通过使用闭包,使得这个函数引用当前的事件对象,参数。
 30 
        
if
 (
!
eventHandle) {
 31 
            elemData.handle 
=
 eventHandle 
=
 
function
 () {
 32 
                
return
 jQuery.event.handle.apply(eventHandle.elem, arguments);
 33 
            };
 34 
        }
 35 
                
 36 
        
//
 使得闭包处理程序可以找到事件源对象
 37 
        eventHandle.elem 
=
 elem;
 38 
 39 
        
//
 
 40 
        handleObj 
=
 { handler: handler, data: data};
 41 
        handleObj.namespace 
=
 
""
;
 42 
 43 
 44 
        handleObj.type 
=
 type;
 45 
        handleObj.guid 
=
 handler.guid;
 46 
 47 
        
//
 每种事件可以有一系列的处理程序,数组形式
 48 
        
var
 handlers 
=
 events[type],
 49 
        special 
=
 jQuery.event.special[type] 
||
 {};
 50 
 51 
        
//
 Init the event handler queue
 52 
        
if
 (
!
handlers) {
 53 
            handlers 
=
 events[type] 
=
 [];
 54 
 55 
            
//
 Check for a special event handler
 56 
            
//
 Only use addEventListener/attachEvent if the special
 57 
            
//
 events handler returns false
 58 
            
//
 完成实际的事件注册
 59 
            
//
 实际的事件处理函数是 eventHandle
 60 
            
if
 (
!
special.setup 
||
 special.setup.call(elem, data, namespaces, eventHandle) 
===
 
false
) {
 61 
                
//
 Bind the global event handler to the element
 62 
                
if
 (elem.addEventListener) {
 63 
                    elem.addEventListener(type, eventHandle, 
false
);
 64 
 65 
                } 
else
 
if
 (elem.attachEvent) {
 66 
                    elem.attachEvent(
"
on
"
 
+
 type, eventHandle);
 67 
                }
 68 
            }
 69 
        }
 70 
 71 
        
//
 自定义的处理函数在一个堆栈中,以后 jQuery.event.handle 到这里找到实际的处理程序
 72 
        handlers.push(handleObj);
 73 
               
 74 
        
//
 Nullify elem to prevent memory leaks in IE
 75 
        elem 
=
 
null
;
 76 
    },
 77 
 78 
    global: {},
 79 
 80 
    
//
 真正的事件处理函数, 
 81 
    
//
 由于是通过  return jQuery.event.handle.apply(eventHandle.elem, arguments) 调用的
 82 
    
//
 所以,此时的 this 就是事件源对象,event 是事件参数
 83 
    handle: 
function
 (event) {  
//
 1904
 84 
        
var
 all, handlers, namespaces, namespace, events;
 85 
 86 
        event 
=
 window.event;
 87 
        event.currentTarget 
=
 
this
;
 88 
 89 
        
//
 在当前的事件对象上找到事件处理列表
 90 
        
var
 events 
=
 jQuery.data(
this
"
events
"
), handlers 
=
 events[event.type];
 91 
 92 
        
if
 (events 
&&
 handlers) {
 93 
            
//
 Clone the handlers to prevent manipulation
 94 
            handlers 
=
 handlers.slice(
0
);
 95 
 96 
            
for
 (
var
 j 
=
 
0
, l 
=
 handlers.length; j 
<
 l; j
++
) {
 97 
                
var
 handleObj 
=
 handlers[j];
 98 
 99 
100 
                
//
 取得注册事件时保存的参数
101 
                event.handler 
=
 handleObj.handler;
102 
                event.data 
=
 handleObj.data;
103 
                event.handleObj 
=
 handleObj;
104 
105 
                
var
 ret 
=
 handleObj.handler.apply(
this
, arguments);
106 
            }
107 
        }
108 
109 
        
return
 event.result;
110 
    },
111 
112 
    
//
 #2020
113 
    special: {}
114 
115 
}
116 
117 
//
 bind 函数定义
118 
jQuery.fn.bind 
=
 
function
( type, fn)
119 
{
120 
    
var
 handler 
=
 fn;
121 
122 
    
//
 调用 jQuery.event.add 添加事件
123 
    
for
 (
var
 i 
=
 
0
, l 
=
 
this
.length; i 
<
 l; i
++
) {
124 
            jQuery.event.add(
this
[i], type, handler);
125 
        }
126 
    
return
 
this
;
127 
}
128 
129 
jQuery.fn.unbind 
=
 
function
 (type, fn) {
130 
    
//
 Handle object literals
131 
    
if
 (
typeof
 type 
===
 
"
object
"
 
&&
 
!
type.preventDefault) {
132 
        
for
 (
var
 key 
in
 type) {
133 
            
this
.unbind(key, type[key]);
134 
        }
135 
136 
    } 
else
 {
137 
        
for
 (
var
 i 
=
 
0
, l 
=
 
this
.length; i 
<
 l; i
++
) {
138 
            jQuery.event.remove(
this
[i], type, fn);
139 
        }
140 
    }
141 
142 
    
return
 
this
;
143 
}
144 // click 事件的注册方法
145 
jQuery.fn.click 
=
 
function
 (fn) {
146 
    
this
.bind(
"
click
"
, fn);
147 
    
return
 
this
;
148 
}

 

 

这样,对于页面上的 id 为 msg 的元素,就可以通过下面的代码注册一个 click 事件处理函数。

 

1 
//
 事件操作
2 
$(
"
#msg
"
).click(
3 
    
function
 () {
4 
        alert(
this
.innerHTML);
5 
    }
6 
    );

 

四、重要的扩展函数 extend

 

在上两篇文章中,我们看到每次要通过 jQuery 的原型增加共享方法的时候,都需要通过 jQuery.fn 一个个进行扩展,非常麻烦,jQuery.fn.extend 提供了一个扩展机制,可以方便我们通过一个或者多个示例对象来扩展某个对象。如果没有指定被扩展的对象,那么将扩展到自己身上。

 

jQuery.extend 也可以通过 jQuery.fn.extend 使用, 在 jQuery 中使用很多,用来为一个目标对象扩展成员,扩展的成员来自于一系列参考对象。

 

这样,如果我们需要为 jQuery.fn 扩展成员 removeData,就可以这样进行。

jQuery.fn.extend(
  {
          removeData: 
function
( key ) {
              
return
 
this
.each(
function
() {
                   jQuery.removeData( 
this
, key );
               });
          }
  }
);

 

 extend 的源码如下,因为比较简单,所以没有做太多的精简。

 

 1 
//
/ <reference path="jQuery-core.js" />
 2 
 3
 4 
jQuery.extend 
=
 jQuery.fn.extend 
=
 
function
 () {
 5 
    
//
 copy reference to target object
 6 
    
var
 target 
=
 arguments[
0
||
 {}, i 
=
 
1
, length 
=
 arguments.length, deep 
=
 
false
, options, name, src, copy;
 7 
 8 
    
//
 深拷贝情况,第一个参数为 boolean 类型,那么,表示深拷贝,第二个参数为目标对象
 9 
    
if
 (
typeof
 target 
===
 
"
boolean
"
) {
10 
        deep 
=
 target;
11 
        target 
=
 arguments[
1
||
 {};
12 
        
//
 skip the boolean and the target
13 
        i 
=
 
2
;
14 
    }
15 
16 
    
//
 如果目标不是对象也不是函数
17 
    
if
 (
typeof
 target 
!==
 
"
object
"
 
&&
 
!
jQuery.isFunction(target)) {
18 
        target 
=
 {};
19 
    }
20 
21 
    
//
 如果只有一个参数就是扩展自己
22 
    
if
 (length 
===
 i) {
23 
        target 
=
 
this
;
24 
        
--
i;
25 
    }
26 
27 
    
//
 遍历所有的参考对象,扩展到目标对象上
28 
    
for
 (; i 
<
 length; i
++
) {
29 
        
//
 Only deal with non-null/undefined values
30 
        
if
 ((options 
=
 arguments[i]) 
!=
 
null
) {
31 
            
//
 Extend the base object
32 
            
for
 (name 
in
 options) {
33 
                src 
=
 target[name];
34 
                copy 
=
 options[name];
35 
36 
                
//
 Prevent never-ending loop
37 
                
if
 (target 
===
 copy) {
38 
                    
continue
;
39 
                }
40 
41 
                
//
 Recurse if we're merging object literal values or arrays
42 
                
if
 (deep 
&&
 copy 
&&
 (jQuery.isPlainObject(copy) 
||
 jQuery.isArray(copy))) {
43 
                    
var
 clone 
=
 src 
&&
 (jQuery.isPlainObject(src) 
||
 jQuery.isArray(src)) 
?
 src
44 
                        : jQuery.isArray(copy) 
?
 [] : {};
45 
46 
                    
//
 Never move original objects, clone them
47 
                    target[name] 
=
 jQuery.extend(deep, clone, copy);
48 
49 
                    
//
 Don't bring in undefined values
50 
                } 
else
 
if
 (copy 
!==
 undefined) {
51 
                    target[name] 
=
 copy;
52 
                }
53 
            }
54 
        }
55 
    }
56 
57 
    
//
 Return the modified object
58 
    
return
 target;
59 
};

 

 

五、ajax

 

对于 xhr 对象来说,我们主要通过异步方式访问服务器,在 onreadystatechange 事件中处理服务器回应的内容。简单的 xhr 使用如下所示。

 

 1 
//
 创建 XHR 对象
 2 
var
 xhr;
 3 
if
 (window.XMLHttpRequest) {
 4 
    xhr 
=
 
new
 XMLHttpRequest();
 5 
}
 6 
else
 
if
 (window.ActiveXObject) {
 7 
    xhr 
=
 
new
 ActiveXObject(
"
Msxml2.XMLHTTP
"
);
 8 
}
 9 
else
 {
10 
    
throw
 
new
 Error(
"
Ajax is not supported by this browser
"
);
11 
}
12 
13 
function
 ready()
14 
{
15 
    alert(
"
Start......
"
);
16 
                
17 
    
//
 通过事件来处理异步请求
18 
    xhr.onreadystatechange 
=
 
function
()
19 
    {
20 
        
if
( xhr.readyState 
==
 
4
 )
21 
        {
22 
            alert( 
"
Ready.
"
);
23 
            
if
( xhr.status 
==
 
200
 )
24 
            {
25 
                alert(
"
成功获得服务器返回的结果.
"
);
26 
                            
27 
                
//
 请求结束之后,可以获取服务器返回的内容
28 
                alert( xhr.responseText );
29 
                
30 
                
//
 获取服务器返回的 json 对象
31 
                
var
 alice 
=
 eval( 
"
(
"
 
+
 xhr.responseText 
+
 
"
)
"
   );
32 
                alert( alice.name );
33 
            }
34 
        }
35 
    };
36 
                
37 
    
//
 设置请求参数
38 
    xhr.open(
"
get
"
"
data.json
"
 );
39 
    xhr.send( 
null
 );
40 
}

 

 

 

jQuery 简单地包装了对 xhr 对象的使用,通过对 jQuery 对象增加常用的访问方法,然后,提供给 jQuery 对象来使用。

 

 1 
//
 主要的扩展在 jQuery.ajax 中。
 2 
jQuery.extend({     
//
 #6299
 3 
    
//
 请求的默认参数
 4 
    ajaxSettings: {
 5 
        url: location.href,
 6 
        type: 
"
GET
"
,
 7 
        contentType: 
"
application/x-www-form-urlencoded
"
,
 8 
        data: 
null
,
 9 
        xhr: window.XMLHttpRequest 
&&
 (window.location.protocol 
!==
 
"
file:
"
 
||
 
!
window.ActiveXObject) 
?
10 
            
function
 () {
11 
                
return
 
new
 window.XMLHttpRequest();
12 
            } :
13 
            
function
 () {
14 
                
try
 {
15 
                    
return
 
new
 window.ActiveXObject(
"
Microsoft.XMLHTTP
"
);
16 
                } 
catch
 (e) { }
17 
            }
18 
        },
19 
20 
    
//
 用来设置 jQuery.ajaxSettings ,设置请求的参数
21 
    ajaxSetup: 
function
 (settings) {
22 
        jQuery.extend(jQuery.ajaxSettings, settings);
23 
    },
24 
25 
    ajax: 
function
 (origSettings) {      
//
 实际的 ajax 函数
26 
        
var
 s 
=
 jQuery.extend(
true
, {}, jQuery.ajaxSettings, origSettings);
27 
28 
        
//
 创建 xhr 对象
29 
        xhr 
=
 s.xhr();
30 
        
//
 回调函数
31 
        
var
 onreadystatechange 
=
 xhr.onreadystatechange 
=
 
function
 (isTimeout) {
32 
            
if
 (xhr.readyState 
===
 
4
) {
33 
                
if
 (xhr.status 
==
 
200
) {
34 
                    s.success.call(origSettings, xhr.responseText);
35 
                }
36 
            }
37 
        };
38 
        
39 
        
//
 设置请求参数
40 
        xhr.open(s.type, s.url);
41 
42 
        
//
 Send the data    发出请求
43 
        xhr.send(s.data);
44 
45 
        
//
 return XMLHttpRequest to allow aborting the request etc.
46 
        
return
 xhr;
47 
    },
48 
49 
    
//
 使用 get 方式发出 ajax 请求的方法
50 
    get: 
function
 (url, data, callback, type) {
51 
        
//
 shift arguments if data argument was omited
52 
        
if
 (jQuery.isFunction(data)) {
53 
            type 
=
 type 
||
 callback;
54 
            callback 
=
 data;
55 
            data 
=
 
null
;
56 
        }
57 
58 
        
return
 jQuery.ajax({
59 
            type: 
"
GET
"
,
60 
            url: url,
61 
            data: data,
62 
            success: callback,
63 
            dataType: type
64 
        });
65 
    }
66 
67 
68 
});       
//
 #6922
69 
70 
//
 扩展 jQuery 对象,增加 load 方法
71 
jQuery.fn.extend(
72 
    {
73 
        load: 
function
 (url) {
74 
            
var
 self 
=
 
this
;
75 
            jQuery.get(url, 
function
 (data) {
76 
                self.each(
function
 () {
77 
                    
this
.innerHTML 
=
 data;
78 
                }       
79 
            )  
80 
            }   
81 
        )
82 
        }
83 
    }
84 
)

 

在页面中,可以如下使用。

 

 1 
<!
DOCTYPE html PUBLIC 
"
-//W3C//DTD XHTML 1.0 Transitional//EN
"
 
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
"
>
 2 
<
html xmlns
=
"
http://www.w3.org/1999/xhtml
"
>
 3 
<
head
>
 4 
    
<
title
><
/
title>
 5 
<
/
head>
 6 
<
body
>
 7 
    
<
input type
=
"
button
"
 id
=
"
btn
"
 value
=
"
Click me
"
 
/
>
 8 
    
<
div id
=
"
msg
"
>
 9 
    
<
/
div>
10 
    
<
script src
=
"
jQuery-core.js
"
 type
=
"
text/javascript
"
><
/
script>
11 
    
<
script src
=
"
jQuery-event-2.js
"
 type
=
"
text/javascript
"
><
/
script>
12 
    
<
script src
=
"
jQuery-data.js
"
 type
=
"
text/javascript
"
><
/
script>
13 
    
<
script src
=
"
jQuery-extend.js
"
 type
=
"
text/javascript
"
><
/
script>
14 
    
<
script src
=
"
jQuery-ajax.js
"
 type
=
"
text/javascript
"
><
/
script>
15 
    
<
script type
=
"
text/javascript
"
>
16 
17 
            $(
"
#btn
"
).click(
function
 () {
18 
                $(
"
#msg
"
).load(
"
hello.txt
"
);
19 
            })
20 
        
21 
22 
    
<
/
script>
23 
<
/
body>
24 
<
/
html>
25 

 

 

前几篇文章中的示例代码,去掉了几个 bug, 这里一起提供下载。

 

 

 

 

 

 

测试页面:

 1 
<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
 2 
<
html 
xmlns
="http://www.w3.org/1999/xhtml"
>
 3 
<
head
>
 4 
    
<
title
></
title
>
 5 
</
head
>
 6 
<
body
>
 7 
    
<
input 
type
="button"
 id
="btn"
 value
="Click me"
 
/>
 8 
    
<
div 
id
="msg"
>
 9 
    
</
div
>
10 
    
<
script 
src
="jQuery-core.js"
 type
="text/javascript"
></
script
>
11 
    
<
script 
src
="jQuery-event-2.js"
 type
="text/javascript"
></
script
>
12 
    
<
script 
src
="jQuery-data.js"
 type
="text/javascript"
></
script
>
13 
    
<
script 
src
="jQuery-extend.js"
 type
="text/javascript"
></
script
>
14 
    
<
script 
src
="jQuery-ajax.js"
 type
="text/javascript"
></
script
>
15 
    
<
script 
type
="text/javascript"
>
16 
17 
        
18 
            $(
"
#btn
"
).click(
function
 () {
19 
                alert(
"
click
"
);
20 
                $(
"
#msg
"
).load(
"
hello.txt
"
);
21 
            })
22 
        
23 
24 
    
</
script
>
25 
</
body
>
26 
</
html
>

 

 

 

转载地址:http://tyenl.baihongyu.com/

你可能感兴趣的文章
mysql联查时为空补全和jdbc获取最后插入生成的id
查看>>
[Android] ArcFace人脸识别 Demo
查看>>
人脸识别 闸机开发分享
查看>>
iOS开发 怎么适配iOS9
查看>>
Jquery选择器性能发现
查看>>
iptables从入门到应用
查看>>
WindowsAPI详解——TerminateProcess 终止|杀死其它进程
查看>>
java入门:dos命令运行java文件
查看>>
MySQL基本知识点
查看>>
自动加入域脚本
查看>>
黑莓10应用多源自Android
查看>>
创建Oracle表空间
查看>>
vm,vbox 虚拟机设置开机自动启动(创建虚拟机快捷方式的命令)
查看>>
用GoAccess分析Nginx的日志
查看>>
我的友情链接
查看>>
iOS客户端调微信支付只出现确定按钮的问题
查看>>
Windows下安装MongoDB
查看>>
virtualbox不能安装64位系统的解决方法
查看>>
选型 - QA testing tools 2/26/2016
查看>>
Linux培训大纲
查看>>