详解jQuery中的getAll()和cleanData()


Posted in jQuery onApril 15, 2019

前言:

看 jQuery 源码的一个痛点就是调用一个函数时,里面会调用 N 个其他函数,然后这 N 个函数里面又会调用 M 个其他其他函数。。

本篇文章主要是对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()方法

总结

以上所述是小编给大家介绍的jQuery中的getAll()和cleanData(),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

jQuery 相关文章推荐
jQuery+ThinkPHP+Ajax实现即时消息提醒功能实例代码
Mar 21 jQuery
jQuery日程管理控件glDatePicker用法详解
Mar 29 jQuery
jQuery实现jQuery-form.js实现异步上传文件
Apr 28 jQuery
jquery.uploadifive插件怎么解决上传限制图片或文件大小问题
May 08 jQuery
浅谈struts1 &amp; jquery form 文件异步上传
May 25 jQuery
jQuery制作input提示内容(兼容IE8以上)
Jul 05 jQuery
jQuery菜单实例(全选,反选,取消)
Aug 28 jQuery
jQuery中each和js中forEach的区别分析
Feb 27 jQuery
基于JQuery实现页面定时弹出广告
May 08 jQuery
jQuery 添加元素和删除元素的方法
Jul 15 jQuery
jQuery实现可以计算进制转换的计算器
Oct 19 jQuery
Jquery Fade用法详解
Nov 06 jQuery
详解JQuery基础动画操作
Apr 12 #jQuery
详解jQuery设置内容和属性
Apr 11 #jQuery
解决JQuery的ajax函数执行失败alert函数弹框一闪而过问题
Apr 10 #jQuery
jQuery中实现text()的方法
Apr 04 #jQuery
基于 jQuery 实现键盘事件监听控件
Apr 04 #jQuery
jQuery分组选择器简单用法示例
Apr 04 #jQuery
jQuery实现带3D切割效果的轮播图功能示例【附源码下载】
Apr 04 #jQuery
You might like
PHP+FastCGI+Nginx配置PHP运行环境
2014/08/07 PHP
PHP语法自动检查的Vim插件
2014/08/11 PHP
thinkphp配置连接数据库技巧
2014/12/02 PHP
PHP+AJAX实现投票功能的方法
2015/09/28 PHP
php获取'/'传参的值简单方法
2017/07/13 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
2017/10/26 PHP
Extjs中DisplayField的日期或者数字格式化扩展
2010/09/03 Javascript
图片onload事件触发问题解决方法
2011/07/31 Javascript
DOM和XMLHttpRequest对象的属性和方法整理
2012/01/04 Javascript
JQ获取动态加载的图片大小的正确方法分享
2013/11/08 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
Nodejs封装类似express框架的路由实例详解
2020/01/05 NodeJs
antdesign-vue结合sortablejs实现两个table相互拖拽排序功能
2021/01/08 Vue.js
[31:33]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第一场
2014/05/23 DOTA
[03:17]2014DOTA2 国际邀请赛中国区预选赛 四强专访
2014/05/23 DOTA
python启动办公软件进程(word、excel、ppt、以及wps的et、wps、wpp)
2009/04/09 Python
Python+django实现文件上传
2016/01/17 Python
python使用opencv读取图片的实例
2017/08/17 Python
一个Python最简单的接口自动化框架
2018/01/02 Python
在pyqt5中QLineEdit里面的内容回车发送的实例
2019/06/21 Python
详解python编译器和解释器的区别
2019/06/24 Python
python如何随机生成高强度密码
2020/08/19 Python
施华洛世奇波兰官网:SWAROVSKI波兰
2019/06/18 全球购物
为您搜罗全球潮流時尚品牌:HBX
2019/12/04 全球购物
经典大学生求职信范文
2014/01/06 职场文书
九年级化学教学反思
2014/01/28 职场文书
《桂花雨》教学反思
2014/04/12 职场文书
2014年干部作风建设总结
2014/10/23 职场文书
2014年维修电工工作总结
2014/11/20 职场文书
赤壁观后感(2)
2015/06/15 职场文书
范文之农村基层党建工作报告
2019/10/24 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python
IDEA2021.2配置docker如何将springboot项目打成镜像一键发布部署
2021/09/25 Java/Android
css3属性选择器 “~”(波浪号) “,”(逗号) “+”(加号)和 “>”(大于号)
2022/04/19 HTML / CSS
Nginx HTTP跳转至HTTPS
2022/05/15 Servers