jqueryon源码,jquery源码实现原理

jQuery绑定事件on

jQuery中用on来绑定事件,常用写法

成都做网站、网站建设,成都做网站公司-成都创新互联已向成百上千家企业提供了,网站设计,网站制作,网络营销等服务!设计与技术结合,多年网站推广经验,合理的价格为您打造企业品质网站。

两种写法哪个更好?

1. $(document).on 将事件委托document, $('#idname').on 将事件绑定到.className元素上。每次document有点击动作,浏览器都会判断当前点击的对象。如果匹配再决定要不要执行,多了个判断环节。JS渲染效率很高,所以此异同基本可以忽略。

2. $("className").on 为onclick绑定,只有在页面onload时执行一次。页面刷新后,新加载的具有className的元素便没有事件绑定到上面了。相反$(document).on这种方法会刷新和重新赋予绑定操作,所以一定程度上更为全面。

Jquery on怎么监测动态事件,代码如下

你可以用事件代理的方式。不用去给每个按钮都绑定click事件,只需要给table绑定click事件。然后通过e.target来判断是不是按钮,如果是按钮,就执行相应的代码。

jQuery on方法传递参数示例

教你如何给

jQuery

on方法绑定的函数传递参数,代码如下:

复制代码

代码如下:

$(".loadingFlower").on("click",'',{name:"123",id:"234",tel:"345"},callback)

function

callback(event){

console.log(event.data.name);

//参数1

=123

console.log(event.data.id);

//参数2

=234

console.log(event.data.tel);

//参数3

=345

}

那些年一直用jQuery处理事件,这些年想了解下内部原理吗

说起jQuery的事件,不得不提一下Dean Edwards大神 addEvent库,很多流行的类库的基本思想从他那儿借来的

jQuery的事件处理机制吸取了JavaScript专家Dean Edwards编写的事件处理函数的精华,使得jQuery处理事件绑定的时候相当的可靠。

在预留退路(graceful degradation),循序渐进以及非入侵式编程思想方面,jQuery也做的非常不错

事件的流程图

总的来说对于JQuery的事件绑定

在绑定的时候做了包装处理

在执行的时候有过滤器处理

.on( events [, selector ] [, data ], handler(eventObject) )

events:事件名

selector : 一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素

data :当一个事件被触发时,要传递给事件处理函数的

handler:事件被触发时,执行的函数

例如:

var body = $('body')

body.on('click','p',function(){

console.log(this)

})

用on方法给body上绑定一个click事件,冒泡到p元素的时候才出发回调函数

这里大家需要明确一点:每次在body上点击其实都会触发事件,但是只目标为p元素的情况下才会触发回调handler

通过源码不难发现,on方法实质只完成一些参数调整的工作,而实际负责事件绑定的是其内部jQuery.event.add方法

on: function( types, selector, data, fn, /*INTERNAL*/ one ) {

var origFn, type;

// Types can be a map of types/handlers

if ( typeof types === "object" ) {

// ( types-Object, selector, data )

if ( typeof selector !== "string" ) {

// ( types-Object, data )

data = data || selector;

selector = undefined;

}

for ( type in types ) {

this.on( type, selector, data, types[ type ], one );

}

return this;

}

if ( data == null fn == null ) {

// ( types, fn )

fn = selector;

data = selector = undefined;

} else if ( fn == null ) {

if ( typeof selector === "string" ) {

// ( types, selector, fn )

fn = data;

data = undefined;

} else {

// ( types, data, fn )

fn = data;

data = selector;

selector = undefined;

}

}

if ( fn === false ) {

fn = returnFalse;

} else if ( !fn ) {

return this;

}

if ( one === 1 ) {

origFn = fn;

fn = function( event ) {

// Can use an empty set, since event contains the info

jQuery().off( event );

return origFn.apply( this, arguments );

};

// Use same guid so caller can remove using origFn

fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );

}

return this.each( function() {

jQuery.event.add( this, types, fn, data, selector );

});

针对事件处理,我们可以拆分2部分:

一个事件预绑定期

一个事件执行期

本章着重讲解事件的预绑定的时候做了那些处理,为什么要这样处理?

事件底层的绑定接口无非就是用addEventListener处理的,所以我们直接定位到addEventListener下面

jQuery.event.add 中有

elem: 目标元素

type: 事件类型,如’click’

eventHandle: 事件句柄,也就是事件回调处理的内容了

false: 冒泡

现在我们把之前的案例给套一下看看

var body = document.getElementsByTagName('body')

var eventHandle = function(){

console.log(this)

}

body .addEventListener( 'click’, eventHandle, false );

明显有问题,每次在body上都触发了回调,少了个p元素的处理,当然这样的效果也无法处理

eventHandle源码

回到内部绑定的事件句柄eventHandle ,可想而知eventHandle不仅仅只是只是充当一个回调函数的角色,而是一个实现了EventListener接口的对象

if ( !(eventHandle = elemData.handle) ) {

eventHandle = elemData.handle = function( e ) {

// Discard the second event of a jQuery.event.trigger() and

// when an event is called after a page has unloaded

return typeof jQuery !== core_strundefined (!e || jQuery.event.triggered !== e.type) ?

jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :

undefined;

};

// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events

eventHandle.elem = elem;

}

可见在eventHandle中并没有直接处理回调函数,而是映射到jQuery.event.dispatch分派事件处理函数了

仅仅只是传入eventHandle.elem,arguments , 就是body元素 与事件对象

那么这里有个问题,事件回调的句柄并没有传递过去,后面的代码如何关联?

本章的一些地方可能要结合后面的dispatch处理才能理清,但是我们还是先看看做了那些处理

on内部的实现机制

我们开从头来理清下jQuery.event.add代码结构,适当的跳过这个环节中不能理解的代码,具体遇到在提出

之前就提到过jQuery从1.2.3版本引入数据缓存系统,贯穿内部,为整个体系服务,事件体系也引入了这个缓存机制

所以jQuery并没有将事件处理函数直接绑定到DOM元素上,而是通过$.data存储在缓存$.cahce上

第一步:获取数据缓存

//获取数据缓存

elemData = data_priv.get( elem );

在$.cahce缓存中获取存储的事件句柄对象,如果没就新建elemData

第二步:创建编号

if ( !handler.guid ) {

handler.guid = jQuery.guid++;

}

为每一个事件的句柄给一个标示,添加ID的目的是 用来寻找或者删除handler,因为这个东东是缓存在缓存对象上的,没有直接跟元素节点发生关联

第三步:分解事件名与句柄

if ( !(events = elemData.events) ) {

events = elemData.events= {};

}

if ( !(eventHandle = elemData.handle) ) {

eventHandle = elemData.handle = function( e ) {

// Discard the second event of a jQuery.event.trigger() and

// when an event is called after a page has unloaded

return typeof jQuery !== core_strundefined (!e || jQuery.event.triggered !== e.type) ?

jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :

undefined;

};

eventHandle.elem = elem;

}

events,eventHandle 都是elemData缓存对象内部的,可见

在elemData中有两个重要的属性,

一个是events,是jQuery内部维护的事件列队

一个是handle,是实际绑定到elem中的事件处理函数

之后的代码无非就是对这2个对象的筛选,分组,填充了

第四步: 填充事件名与事件句柄

// Handle multiple events separated by a space

// jQuery(...).bind("mouseover mouseout", fn);

// 事件可能是通过空格键分隔的字符串,所以将其变成字符串数组

// core_rnotwhite:/\S+/g

types = ( types || "" ).match( core_rnotwhite ) || [""];

// 例如:'.a .b .c'.match(/\S+/g) → [".a", ".b", ".c"]

// 事件的个数

t = types.length;

while ( t-- ) {

// 尝试取出事件的命名空间

// 如"mouseover.a.b" → ["mouseover.a.b", "mouseover", "a.b"]

tmp = rtypenamespace.exec( types[t] ) || [];

// 取出事件类型,如mouseover

type = origType = tmp[1];

// 取出事件命名空间,如a.b,并根据"."分隔成数组

namespaces = ( tmp[2] || "" ).split( "." ).sort();

// There *must* be a type, no attaching namespace-only handlers

if ( !type ) {

continue;

}

// If event changes its type, use the special event handlers for the changed type

// 事件是否会改变当前状态,如果会则使用特殊事件

special = jQuery.event.special[ type ] || {};

// If selector defined, determine special event api type, otherwise given type

// 根据是否已定义selector,决定使用哪个特殊事件api,如果没有非特殊事件,则用type

type = ( selector ? special.delegateType : special.bindType ) || type;

// Update special based on newly reset type

// type状态发生改变,重新定义特殊事件

special = jQuery.event.special[ type ] || {};

// handleObj is passed to all event handlers

// 这里把handleObj叫做事件处理对象,扩展一些来着handleObjIn的属性

handleObj = jQuery.extend({

type: type,

origType: origType,

data: data,

handler: handler,

guid: handler.guid,

selector: selector,

needsContext: selector jQuery.expr.match.needsContext.test( selector ),

namespace: namespaces.join(".")

}, handleObjIn );

// Init the event handler queue if we're the first

// 初始化事件处理列队,如果是第一次使用,将执行语句

if ( !(handlers = events[ type ]) ) {

handlers = events[ type ] = [];

handlers.delegateCount = 0;

// Only use addEventListener if the special events handler returns false

// 如果获取特殊事件监听方法失败,则使用addEventListener进行添加事件

if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

if ( elem.addEventListener ) {

elem.addEventListener( type, eventHandle, false );

}

}

}

// 特殊事件使用add处理

if ( special.add ) {

special.add.call( elem, handleObj );

// 设置事件处理函数的ID

if ( !handleObj.handler.guid ) {

handleObj.handler.guid = handler.guid;

}

}

// Add to the element's handler list, delegates in front

// 将事件处理对象推入处理列表,姑且定义为事件处理对象包

if ( selector ) {

handlers.splice( handlers.delegateCount++, 0, handleObj );

} else {

handlers.push( handleObj );

}

// Keep track of which events have ever been used, for event optimization

// 表示事件曾经使用过,用于事件优化

jQuery.event.global[ type ] = true;

}

// Nullify elem to prevent memory leaks in IE

// 设置为null避免IE中循环引用导致的内存泄露

elem = null;

},

这段比较长了分解下,最终的目的就是为填充events,eventHandle

简单易懂的jQuery导航(三级菜单)源码

!-- 三级操蛋导航 --

div class="nav_left"

div class="nav_leftlist"

h2b/b用户系统/h2

dl

dtb/b用户管理/dt

dd

a class="cur" href=""商户信息b/b/a

a href=""用户信息b/b/a

/dd

/dl

/div

div class="nav_leftlist"

h2b/b财务系统/h2

dl

dtb/b系统账务/dt

dd

a href=""平台账单b/b/a

a href=""账单明细b/b/a

/dd

/dl

dl

dtb/b商户账务/dt

dd

a href=""商户账单b/b/a

a href=""提现管理b/b/a

/dd

/dl

dl

dtb/b用户账务/dt

dd

a href=""用户账单b/b/a

a href=""提现管理b/b/a

/dd

/dl

/div

/div

style

.nav_left{background: #232b35;height: 100%;width: 220px;min-height: 600px;position: fixed;top: 100px;left: 0;}

.nav_leftlist{}

.nav_leftlist h2{height: 50px;line-height: 50px;padding-left: 40px;font-size: 16px;background: #3b444f;color: #999999;position: relative;cursor: pointer;}

.nav_leftlist h2 b{position: absolute;top: 20px;left: 13px;width: 16px;height: 9px;background: url(../images/icon04.png) no-repeat;background-position: 0 0;cursor: pointer;}

.nav_leftlist h2 b.cur{background-position: -16px 0;}

.nav_leftlist dl{}

.nav_leftlist dl dt{height: 50px;line-height: 50px;background: #2c3643;font-size: 16px;color: #ffffff;padding-left: 60px;position: relative;cursor: pointer;}

.nav_leftlist dl dt b{position: absolute;top: 20px;left: 34px;width: 16px;height: 9px;background: url(../images/icon04.png) no-repeat;background-position: 0 -10px;}

.nav_leftlist dl dt b.cur{background-position: -16px -10px;}

.nav_leftlist dl dd{}

.nav_leftlist dl dd a{display: block;height: 50px;line-height: 50px;color: #fff;padding-left: 80px;font-size: 16px;position: relative;}

.nav_leftlist dl dd a.cur{color: #ee581c;}

.nav_leftlist dl dd a.cur b{display: block;position: absolute;top: 16px;right: -1px;width: 11px;height: 18px;background: url(../images/icon04.png) no-repeat;background-position: 0 -20px;}

/style

/body

script type="text/javascript" src="../js/jquery.js" /script

script type="text/javascript" 

$(function(){

$('.nav_leftlist').on('click', 'h2', function(event) {

$(this).siblings('dl').toggle();

if($(this).siblings('dl').css('display')=='none'){

$(this).find('b').addClass('cur');

}else{

$(this).find('b').removeClass('cur');

}

});

$('.nav_leftlist').on('click', 'dl dt', function(event) {

$(this).siblings('dd').toggle();

if($(this).siblings('dd').css('display')=='none'){

$(this).find('b').addClass('cur');

}else{

$(this).find('b').removeClass('cur');

}

});

})

/script

效果图:

完全理解jQuery源代码,在前端行业算什么水平

依读了2周jQuery源码的人感觉来说,完全理解jQuery,就拿jQuery 1.11这个版本10337行代码来说,水平已经很不错了。谦虚点说,已经入门。骄傲点,国内领先水平。但其码我感觉是js架构之路起行的第一步,完全理解源码,说明有独立构建或组织大型web前端框架的能力和基础。然后看看完全理解jQuery是一个怎么样的状态。

看下面几个链接就明白了:

RubyLouvre/avalon · GitHub

artDialog

aui/artDialog · GitHub(后来的新版代码有所改变)

没错,这两个里边,就是在继承jquery的基础上做了自己的创新尝试。

然后在看下面这位:

[原创] jQuery1.6.1源码分析系列(停止更新)

是唯一出过jquery源码分析书的一位:

《jQuery技术内幕:深入解析jQuery架构设计与实现原理》(高云)【摘要 书评 试读】

然后在看这位:

jQuery 2.0.3 源码分析系列

是目前一直在更新的一位,通俗有深度且版本比较新。

在说一下我2周阅读jquery源码的心得,初看源码写的恶心,再看写的不错,细看写的真是精妙。然后今天在看ext 4.2的源码,真是流畅易读。基本来说,看懂jQuery源码,以后的源码学习之路可以说,平坦。

然后说是不是高手,高手只是一个自我定位的心理暗示,是一种人格魅力的体现,是业务与技术的完美结合。个人感觉只能无限的接近,不能在有限的生命里边到达。我们在通往目的地过程中享受一路的风景,这才是生命的意义。

然后在说前端,前端的核心是js,外围打酱油的技术太多,不一一列举。

css就像一瓶酒,得品。

html,css总共就那些标签跟选择器属性什么的,但是要写一个有扩展性,健壮性或维护性的页面不容易。现在写页面基本条件反射,不是如何快速的完成,而是思考如果有前端界面需求修改,怎么在修改代码最少的情况下完成整体需求任务。

js就像一把剑,得磨。

js刚开始只是为了较验,随便技术社会的发展,承担的角色越来越重,刚开始玩玩jQuery感觉已经会js了,其实只是冰山一角。随着对js的了解越来越多,他即变态又可爱,即好玩又难控,即有很多兼容问题,但解决兼容是我们基本生存之道。

人生就是一场梦,得作。

技术只是生活的一部分,曾经雄心斗志,如今低头写码。改变能改变的,接受不能改变的。人生有限,兄争朝夕啊。

最后说,什么时候能阅读jQuery源码,我感觉其码是纯js编码一年以上,js基础知识没有盲点。阅读源码,确实能学到很多东西。不只是技术,而是一种生活的态度。一种把一件事情做到极致的态度


分享名称:jqueryon源码,jquery源码实现原理
文章位置:http://azwzsj.com/article/dsddcho.html