详解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实现tab键进行选择后enter键触发click行为
Mar 29 jQuery
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
Apr 10 jQuery
jQuery实现鼠标滑过预览图片大图效果的方法
Apr 26 jQuery
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
Jun 11 jQuery
jQuery响应滚动条事件功能示例
Oct 14 jQuery
jquery ztree实现右键收藏功能
Nov 20 jQuery
jQuery实现动态显示select下拉列表数据的方法
Feb 05 jQuery
jQuery实现模糊查询的方法分析
May 10 jQuery
jQuery超简单遮罩层实现方法示例
Sep 06 jQuery
详解jQuery-each()方法
Mar 13 jQuery
jQuery HTML css()方法与css类实例详解
May 20 jQuery
jquery实现简易验证插件封装
Sep 13 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
Win9x/ME下Apache+PHP安装配置
2006/10/09 PHP
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
2007/02/15 PHP
深入了解PHP中的Array数组和foreach
2016/11/06 PHP
关于PHP内置的字符串处理函数详解
2017/02/04 PHP
javascript背投广告代码的完善
2008/04/08 Javascript
javascript 命名空间以提高代码重用性
2008/11/13 Javascript
禁用页面部分JavaScript方法的具体实现
2013/07/31 Javascript
返回页面顶部top按钮通过锚点实现(自写)
2013/08/30 Javascript
深入了解Node.js中的一些特性
2014/09/25 Javascript
JavaScript中常用的六种互动方法示例
2015/03/13 Javascript
微信小程序 canvas API详解及实例代码
2016/10/08 Javascript
BootStrap表单验证实例代码
2017/01/13 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
2017/03/17 Javascript
原生js实现密码输入框值的显示隐藏
2017/07/17 Javascript
JS实现DOM节点插入操作之子节点与兄弟节点插入操作示例
2018/07/30 Javascript
深入理解react-router 路由的实现原理
2018/09/26 Javascript
详解koa2学习中使用 async 、await、promise解决异步的问题
2018/11/13 Javascript
Nodejs实现微信分账的示例代码
2021/01/19 NodeJs
[00:49]完美世界DOTA2联赛10月28日开团时刻:随便打
2020/10/29 DOTA
零基础写python爬虫之爬虫编写全记录
2014/11/06 Python
Python脚本实现网卡流量监控
2015/02/14 Python
django 在原有表格添加或删除字段的实例
2018/05/27 Python
Python实现的本地文件搜索功能示例【测试可用】
2018/05/30 Python
Python中logging实例讲解
2019/01/17 Python
Flask框架钩子函数功能与用法分析
2019/08/02 Python
Pyqt5自适应布局实例
2019/12/13 Python
科颜氏美国官网:Kiehl’s美国
2017/01/31 全球购物
市场营销专业个人自荐信格式
2013/09/21 职场文书
顶岗实习计划书
2014/01/10 职场文书
旅游个人求职信范文
2014/01/30 职场文书
大学生新学期计划书
2014/04/28 职场文书
党的群众路线教育实践活动组织生活会发言材料
2014/10/17 职场文书
不服劳动仲裁起诉书
2015/05/20 职场文书
运动员代表致辞
2015/07/29 职场文书
2016学习医德医风心得体会
2016/01/25 职场文书
JS数组去重详情
2021/11/07 Javascript