`
xxh123
  • 浏览: 33114 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类

jquery源码的学习

 
阅读更多

1  js中的对象都是object,使用firebug查看都是Object:{}形式,js中的function默认返回的是this对象,任何代码只要知道this对象那么就比较容易的理解,jquery中绝大多数的this对象都是一个数组对象,可以广泛的支持设计的需要。

2  createDocumentFragment主要可以提高效率。可以配合缓存使用,这个主要是通过jquery对象的fragement属性来实现。

3  动态方法apply和call的广泛的使用和isFunction,isObject等方法的使用。

4  初始化中的new jQuery.fn.init中的 jQuery.fn为jQuery的prototype,方便闭包的实现和可扩展性,而且jQuery.fn.init.prototype=jQuery.fn,所以 jQuery.fn=== jQuery.prototype===jQuery.fn.init.prototype。

5   正则表达式的使用,靠,看了好久终于看懂了一些,比较的强大,对一些基本的操作进行了比较完美的分类。反正我是想不到啦。

6     var getData = function(elem, key){ 
        return1 && 2 || null;  //如果缓存里没有, 返回null 
    } 

这里有点linux的味道,如果1和2都是true则返回2的结果,否则返回null

6 大量使用闭包,即匿名function,可以有效的减少js的冲突,增加可用性。

 

   平时我们都是调用 click(func) 之类的函数, 而其实这些都是工具函数,真正和事件挂钩的函数是

  jQuery.fn.bind - 调用 jQuery.event.add

 jQuery.fn.unbind - 调用 jQuery.event.remove

 jQuery.fn.trigger - 调用 jQuery.event.trigger

 jQuery.fn.one - 调用 jQuery.fn.bind,Query.fn.unbind

要想知道jQuery的事件原理,必须读 jQuery.event.add

 

add: function ( elem, types, handler, data ) {

// 只对节点操作。
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return ;
}

// IE 无法传递 window,而是复制这个对象 。
if ( jQuery.isWindow( elem ) && ( elem !== window && ! elem.frameElement ) ) {
elem
= window;
}

// 如果 handler === false, 也就是说就是阻止某事件,
// 这样只要 bind("evt", false); 就是阻止此事件。
if ( handler === false ) {
handler
= returnFalse;
}
else if ( ! handler ) {
return ;
}

// handleObjIn 是内部处理句柄, handleObj 是直接使用的处理句柄。
var handleObjIn, handleObj;

if ( handler.handler ) {
handleObjIn
= handler;
handler
= handleObjIn.handler;
}

// 为函数生成唯一的 guid 。具体下面介绍。
if ( ! handler.guid ) {
handler.guid
= jQuery.guid ++ ;
}

// 获取一个节点的数据。
var elemData = jQuery.data( elem );

// 如果没有数据,则直接返回。
if ( ! elemData ) {
return ;
}

// 避免和原生的js对象混淆。
var eventKey = elem.nodeType ? " events " : " __events__ " ,

// 这里就是关键。
// elemData 是存储数据的位置, 而 elemData[ eventKey ] 就是存储当前事件的对象。 elemData.handle 就是当前绑定的所有函数数组。
// 也就是说,当我们绑定一个函数时,会往 elemData.handle 放这个函数,然后事件触发时,会遍历 elemData.handle 中函数然后去执行。
// 肯能有人会问,为什么这么做,因为原生的DOM内部也有一个 函数数组,事件触发后会执行全部函数。答案还是 兼容。
// 标准浏览器使用 addEventListener
// IE 使用 attachEvent
// 而这2者还是有差距的。因为 addEventListener 执行函数的顺序即添加函数的顺序,然而 attachEvent 执行函数的顺序和添加的顺序是相反的。
// jQuery 使用自定义的 handler 数组,好处有:
// 因为最后仅绑定一次原生事件,事件触发后,手动执行 数组中的函数。这样保证兼容。
// 同时也可以知道到底绑定了什么函数,可以方便 trigger 函数的完成。

events
= elemData[ eventKey ],
eventHandle
= elemData.handle;

// 一些功能。。
if ( typeof events === " function " ) {
eventHandle
= events.handle;
events
= events.events;

}
else if ( ! events ) {
if ( ! elem.nodeType ) {
elemData[ eventKey ]
= elemData = function (){};
}

elemData.events
= events = {};
}

// 如果是第一次执行,需创建 eventHandle
if ( ! eventHandle ) {

// eventHandle 就是真正绑定到原生事件的那个函数,这个函数用来执行events.hadlers 用。
elemData.handle = eventHandle = function () {
// Handle the second event of a trigger and when
// an event is called after a page has unloaded
return typeof jQuery !== " undefined " && ! jQuery.event.triggered ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
}

// 绑定函数和原生,这样可以保证函数可执行为目前作用域。
eventHandle.elem = elem;

// 处理 jQuery(...).bind("mouseover mouseout", fn);
types = types.split( " " );

var type, i = 0 , namespaces;

while ( (type = types[ i ++ ]) ) {
handleObj
= handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };

//

// 绑定 type guid
handleObj.type = type;
if ( ! handleObj.guid ) {
handleObj.guid
= handler.guid;
}

// 获取当前的函数数组。
var handlers = events[ type ],
special
= jQuery.event.special[ type ] || {};

// 如果第一次,则创建这个数组。
if ( ! handlers ) {
handlers
= events[ type ] = [];

// 特殊事件要执行 setup 而不是标准 addEventListener。
// 此行用来支持自定义的事件。
if ( ! special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
// 标准事件。 这里绑定的为 eventHandle
if ( elem.addEventListener ) {
elem.addEventListener( type, eventHandle,
false );

}
else if ( elem.attachEvent ) {
elem.attachEvent(
" on " + type, eventHandle );
}
}
}

// 自定义事件,执行 add
if ( special.add ) {
special.add.call( elem, handleObj );

if ( ! handleObj.handler.guid ) {
handleObj.handler.guid
= handler.guid;
}
}

// 不管是不是首次,都放入目前绑定的函数。
handlers.push( handleObj );

// 为实现 trigger 。
jQuery.event.global[ type ] = true ;
}

// 让IE下可以正常回收 elem 内存。
elem = null ;
},


8.2 事件对象

    框架的义务当然也包括 事件参数的修复。jQuery 是自定义事件对象, 这个对象模拟真实事件对象。

    根据上文可以知道,真正绑定事件的是一个函数,这个函数执行时会先 生成自定义事件对象, 然后把此对象作为参数调用所有的 handler 。

     jQuery 自定义事件是 jQuery.Event 。 (代码  2583-2610 行)

jQuery.Event = function ( src ) {
// 支持 没有 new jQuery.Event
if ( ! this .preventDefault ) {
return new jQuery.Event( src );
}

//

}

    // 处理字符串参数,分七种情形:

     //①单个标签,带对象属性包           --->   jQuery.merge
     //②单个标签,不带对象属性包         --->   attr + jQuery.merge
     //③复杂的HTML片断                 --->   buildFragment + jQuery.merge
     //④ID选择器,与找到的元素的ID不同   --->   getElementById + Sizzle + pushStack
     //⑤ID选择器,与找到的元素的ID相同   --->   getElementById + 简单属性添加
     //⑥标签选择器                     --->   getElementsByTagName + jQuery.merge

     //⑦其他CSS表达式                  --->   Sizzle + pushStack

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics