内容简介:看 jQuery 源码的一个痛点就是调用一个函数时,里面会调用 N 个其他函数,然后这 N 个函数里面又会调用 M 个其他其他函数。。本篇文章主要是对上篇文章—[jQuery源码解析之detach()/empty()/remove()/unwrap()]() 中两个函数
前言:
看 jQuery 源码的一个痛点就是调用一个函数时,里面会调用 N 个其他函数,然后这 N 个函数里面又会调用 M 个其他其他函数。。
本篇文章主要是对上篇文章—[jQuery源码解析之detach()/empty()/remove()/unwrap()]() 中两个函数 getAll 和 cleanData() 进行解析。
一、getAll(context, tag)
作用:
用来获取 context 上的 tag 标签,或者是将 context 和 context 里的 tag 标签的元素合并
源码:
//一般是传的node,'script'
//应该是用来获取context上的tag标签,或者是将context和context里的tag标签的元素合并
//源码4893行
function getAll( context, tag ) {
// Support: IE <=9 - 11 only
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
var ret;
console.log(context,typeof context.getElementsByTagName,typeof context.querySelectorAll,'context4894')
//如果context存在getElementsByTagName的方法的话
if ( typeof context.getElementsByTagName !== "undefined" ) {
//tag:script
//从context中获取script标签的节点
ret = context.getElementsByTagName( tag || "*" )
console.log(tag,ret,'ret4897')
}
//DocumentFragment没有getElementsByTagName方法,但有querySelectorAll方法
else if ( typeof context.querySelectorAll !== "undefined" ) {
ret = context.querySelectorAll( tag || "*" );
} else {
ret = [];
}
console.log(nodeName( context, tag ),'nodeName4909')
//nodeName() 判断两个参数的nodename是否相等
if ( tag === undefined || tag && nodeName( context, tag ) ) {
return jQuery.merge( [ context ], ret );
}
return ret;
}
注意:DocumentFragment 没有 getElementsByTagName 方法,但有 querySelectorAll 方法!
二、 $ .merge()
作用:
合并两个数组内容到第一个数组
源码:
// Support: Android <=4.0 only, PhantomJS 1 only
// push.apply(_, arraylike) throws on ancient WebKit
//源码461行
//将second合并到first后面
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
//依次将second的item添加到first后面
for ( ; j < len; j++ ) {
first[ i++ ] = second[ j ];
}
//first可能是类数组,所以需要更新下length属性
first.length = i;
return first;
},
需要注意的是最后的 first.length = i
三、cleanData()
作用:
清除元素节点上的事件和数据
源码:
//清除elems上的数据和事件
//源码6146行
cleanData: function( elems ) {
var data, elem, type,
//beforeunload/blur/click/focus/focusin/focusout/
//load/mouseenter/mouseleave/pointerenter/pointerleave
special = jQuery.event.special,
i = 0;
for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
//允许的节点类型
if ( acceptData( elem ) ) {
//当有事件绑定到elem后,jQuery会给elem一个属性dataPriv.expando
//该属性上面就绑定了事件和数据
if ( ( data = elem[ dataPriv.expando ] ) ) {
//如果data上有事件的话
if ( data.events ) {
//逐个列举data上的事件,比如click
for ( type in data.events ) {
// 如果special中有data.events上的事件
if ( special[ type ] ) {
//调用jQuery.event.remove方法,移除elem上的event类型
jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
}
//应该是自定义的事件
else {
//本质即elem.removeEventListener(type,handle)
jQuery.removeEvent( elem, type, data.handle );
}
}
}
// Support: Chrome <=35 - 45+
// Assign undefined instead of using delete, see Data#remove
//最后将元素的dataPriv.expando属性置为undefined
elem[ dataPriv.expando ] = undefined;
}
//dataUser应该是用户绑定的事件
if ( elem[ dataUser.expando ] ) {
// 将元素的dataUser.expando属性置为undefined
// Support: Chrome <=35 - 45+
// Assign undefined instead of using delete, see Data#remove
elem[ dataUser.expando ] = undefined;
}
}
}
}
解析:
① 依次判断 elems[i] 是否是元素节点/文档节点/对象
② 再判断 elem 的 dataPriv.expando 属性是否有 events 属性
③ 当 events 里有 jQuery.event.special 指定的 事件类型时,
使用 jQuery.event.remove(elem,type) 移除事件和数据
④ 反之,则使用 jQuery.removeEvent(elem,type,data.handle) 移除事件和数据
⑤ 将 elem[dataPriv.expando] 置为 undefined
⑥ 将 elem[dataUser.expando] 置为 undefined
四、acceptData()
作用:
判断是否是指定的节点类型,返回 true/false
源码:
//判断是否是指定的节点类型
//只接受元素节点1,文档节点9,任意对象
//返回true/false
//源码4178行
var acceptData = function( owner ) {
// Accepts only:
// - Node
// - Node.ELEMENT_NODE
// - Node.DOCUMENT_NODE
// - Object
// - Any
return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
}
注意:
Object 类型的 nodeType 是 undefined
五、 $ .removeEvent()
作用:
移除 elem 上的自定义监听事件
源码:
//移除elem上的自定义监听事件
//源码5599行
//jQuery.removeEvent(elem,type,data.handle)
jQuery.removeEvent = function( elem, type, handle ) {
// This "if" is needed for plain objects
if ( elem.removeEventListener ) {
elem.removeEventListener( type, handle );
}
}
本质即调用原生JS的 removeEventListener() 方法
(完)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Build Your Own Web Site the Right Way Using HTML & CSS
Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95
Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!