详解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 EasyUI 组件加上清除功能的方法(详解)
Apr 13 jQuery
Jquery获取radio选中的值
May 05 jQuery
jQuery ajax动态生成table功能示例
Jun 14 jQuery
jQuery Collapse1.1.0折叠插件简单使用
Aug 28 jQuery
实现jquery放大镜的两种方法
Feb 22 jQuery
jQuery幻灯片插件owlcarousel参数说明中文文档
Feb 27 jQuery
jQuery插件jsonview展示json数据
May 26 jQuery
jQuery扩展方法实现Form表单与Json互相转换的实例代码
Sep 05 jQuery
jQuery+Datatables实现表格批量删除功能【推荐】
Oct 24 jQuery
浅谈JS和jQuery的区别
Mar 27 jQuery
Jquery实现获取子元素的方法分析
Aug 24 jQuery
jQuery 动态粒子效果示例代码
Jul 07 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的ASCII码转换类
2013/07/05 PHP
Thinkphp自定义生成缩略图尺寸的方法
2019/08/05 PHP
实现复选框全选/全不选切换
2006/12/23 Javascript
用jscript实现新建和保存一个word文档
2007/06/15 Javascript
javascript中万恶的function实例分析
2011/05/25 Javascript
js String对象中常用方法小结(字符串操作)
2012/01/27 Javascript
js 代码优化点滴记录
2012/02/19 Javascript
javascript函数声明和函数表达式区别分析
2014/12/02 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
jquery中键盘事件小结
2016/02/24 Javascript
JavaScript导航脚本判断当前导航
2016/07/12 Javascript
Vue.js学习笔记之 helloworld
2016/08/14 Javascript
JS高级运动实例分析
2016/12/20 Javascript
微信小程序实现跑马灯效果完整代码(附效果图)
2018/05/30 Javascript
jquery实现Ajax请求的几种常见方式总结
2019/05/28 jQuery
JavaScript变量作用域及内存问题实例分析
2019/06/10 Javascript
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
vue 清空input标签 中file的值操作
2020/07/21 Javascript
jQuery实现雪花飘落效果
2020/08/02 jQuery
如何使用RoughViz可视化Vue.js中的草绘图表
2021/01/30 Vue.js
[10:49]2014国际邀请赛 叨叨刀塔第二期为真正的电竞喝彩
2014/07/21 DOTA
python多线程抓取天涯帖子内容示例
2014/04/03 Python
Python面向对象之接口、抽象类与多态详解
2018/08/27 Python
python 利用turtle模块画出没有角的方格
2019/11/23 Python
详解css3 Transition属性(平滑过渡菜单栏案例)
2017/09/05 HTML / CSS
css3实现元素环绕中心点布局的方法示例
2019/01/15 HTML / CSS
Tiqets英国:智能手机上的文化和娱乐门票
2019/07/10 全球购物
一套.net面试题及答案
2016/11/02 面试题
请解释接口的显式实现有什么意义
2012/05/26 面试题
采购内勤岗位职责
2013/12/10 职场文书
小学教师办公室制度
2014/02/03 职场文书
《莫高窟》教学反思
2014/02/25 职场文书
大学第二课堂活动总结
2014/07/08 职场文书
2015年教学管理工作总结
2015/05/20 职场文书
Python连续赋值需要注意的一些问题
2021/06/03 Python
英镑符号 £
2022/02/17 杂记