详解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 相关文章推荐
简单谈谈require模块化jquery和angular的问题
Jun 23 jQuery
jQuery实现点击关注和取消功能
Jul 03 jQuery
jQuery常用选择器详解
Jul 17 jQuery
利用jQuery异步上传文件的插件用法详解
Jul 19 jQuery
jQuery:unbind方法的使用详解
Aug 14 jQuery
jQuery实现简单的计时器功能实例分析
Aug 29 jQuery
jquery实现左右轮播图效果
Sep 28 jQuery
jQuery点击页面其他部分隐藏下拉菜单功能
Nov 27 jQuery
jQuery插件实现非常实用的tab栏切换功能【案例】
Feb 18 jQuery
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
May 04 jQuery
jquery多级树形下拉菜单的实例代码
Jul 09 jQuery
jQuery HTML css()方法与css类实例详解
May 20 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递归实现无限分类 格式化数组的详解
2013/06/08 PHP
php基于自定义函数记录log日志方法
2017/07/21 PHP
微信公众号实现扫码获取微信用户信息(网页授权)
2019/04/09 PHP
Javascript 网页水印(非图片水印)实现代码
2010/03/01 Javascript
通过复制Table生成word和excel的javascript代码
2014/01/20 Javascript
jquery数组过滤筛选方法grep()简介
2014/06/06 Javascript
基于javascript实现判断移动终端浏览器版本信息
2014/12/09 Javascript
JavaScript获取Url里的参数
2014/12/18 Javascript
jQuery简单实现列表隐藏和显示效果示例
2016/09/12 Javascript
Vue常用指令V-model用法
2017/03/08 Javascript
React Native 通告消息竖向轮播组件的封装
2020/08/25 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
CentOS环境中MySQL修改root密码方法
2018/01/07 Javascript
解决VUEX兼容IE上的报错问题
2018/03/01 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
2018/10/22 Javascript
vue使用el-upload上传文件及Feign服务间传递文件的方法
2019/03/15 Javascript
js比较两个单独的数组或对象是否相等的实例代码
2019/04/28 Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
多页vue应用的单页面打包方法(内含打包模式的应用)
2020/06/11 Javascript
解决vue-router路由拦截造成死循环问题
2020/08/05 Javascript
jQuery实现简单评论功能
2020/08/19 jQuery
Js实现粘贴上传图片的原理及示例
2020/12/09 Javascript
12个Python程序员面试必备问题与答案(小结)
2019/06/24 Python
python英语单词测试小程序代码实例
2019/09/09 Python
python对象转字典的两种实现方式示例
2019/11/07 Python
python绘图模块之利用turtle画图
2021/02/12 Python
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
新加坡最佳婴儿用品店:Mamahood.com.sg
2018/08/26 全球购物
安全施工责任书
2014/08/25 职场文书
高中军训的心得体会
2014/09/01 职场文书
社区四风存在问题及整改措施
2014/10/26 职场文书
保研导师推荐信
2015/03/25 职场文书
硕士学位申请报告
2015/05/15 职场文书
在校证明模板
2015/06/17 职场文书
如何用Laravel包含你自己的帮助函数
2021/05/27 PHP
【js设计模式】SOLID五大设计原则
2022/03/24 Javascript