详解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.uploadifive插件怎么解决上传限制图片或文件大小问题
May 08 jQuery
JQuery Ajax 异步操作之动态添加节点功能
May 24 jQuery
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
Jun 09 jQuery
jQuery动态添加li标签并添加属性和绑定事件方法
Feb 24 jQuery
轻松搞定jQuery+JSONP跨域请求的解决方案
Mar 06 jQuery
jQuery 实现倒计时天,时,分,秒功能
Jul 31 jQuery
jQuery分组选择器简单用法示例
Apr 04 jQuery
JQuery事件委托原理与用法实例分析
May 13 jQuery
jQuery实现图片随机切换、抽奖功能(实例代码)
Oct 23 jQuery
JQuery获得内容和属性方法解析
May 30 jQuery
jquery实现简单拖拽效果
Jul 20 jQuery
jQuery中getJSON跨域原理的深入讲解
Sep 02 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
解决控件遮挡问题:关于有窗口元素和无窗口元素
2007/01/28 PHP
PHP中数组合并的两种方法及区别介绍
2012/09/14 PHP
php统计数组元素个数的方法
2015/07/02 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
Laravel中正确地返回HTTP状态码方法示例
2019/09/10 PHP
js跟随滚动条滚动浮动代码
2009/12/31 Javascript
FusionCharts图表显示双Y轴双(多)曲线
2012/11/22 Javascript
js自动查找select下拉的菜单并选择(示例代码)
2014/02/26 Javascript
AngularJS入门教程(一):静态模板
2014/12/06 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
纯JavaScript实现的兼容各浏览器的添加和移除事件封装
2015/03/28 Javascript
jquery 插件实现瀑布流图片展示实例
2015/04/03 Javascript
将JavaScript的jQuery库中表单转化为JSON对象的方法
2015/11/17 Javascript
理解jquery事件冒泡
2016/01/03 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
vue 文件目录结构详解
2017/11/24 Javascript
js中DOM事件绑定分析
2018/03/18 Javascript
浅谈js获取ModelAndView值的问题
2018/03/28 Javascript
详解如何创建并发布一个 vue 组件
2018/11/08 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
2019/09/01 Javascript
如何检测JavaScript中的死循环示例详解
2020/08/30 Javascript
使用Python的内建模块collections的教程
2015/04/28 Python
django站点管理详解
2017/12/12 Python
Python函数和模块的使用总结
2019/05/20 Python
python3实现带多张图片、附件的邮件发送
2019/08/10 Python
Python使用itcaht库实现微信自动收发消息功能
2020/07/13 Python
一款纯css3实现的动画加载导航
2014/10/08 HTML / CSS
女士鞋子、包包和服装在线,第一款10美元:ShoeDazzle
2019/07/26 全球购物
益模软件Java笔试题
2012/03/27 面试题
远程调用的原理
2014/07/05 面试题
Ruby如何定义一个类
2012/10/08 面试题
学校体育节班级口号
2015/12/25 职场文书
《穷人》教学反思
2016/02/19 职场文书
年中了,该如何写好个人述职报告?
2019/07/02 职场文书
vue+springboot实现登录验证码
2021/05/27 Vue.js
python井字棋游戏实现人机对战
2022/04/28 Python