详解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实现字体颜色渐变效果的方法
Mar 29 jQuery
jQuery tip提示插件(实例分享)
Apr 28 jQuery
jQuery封装placeholder效果实现方法,让低版本浏览器支持该效果
Jul 08 jQuery
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
JS和JQuery实现雪花飘落效果
Nov 30 jQuery
Vue引入jquery实现平滑滚动到指定位置
May 09 jQuery
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
Jun 05 jQuery
使用jQuery动态设置单选框的选中效果
Dec 06 jQuery
jQuery实现模拟搜索引擎的智能提示功能简单示例
Jan 27 jQuery
jQuery中each和js中forEach的区别分析
Feb 27 jQuery
jQuery实现动态添加和删除input框实例代码
Mar 26 jQuery
jquery实现动态改变css样式的方法分析
May 27 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
经典的星际争霸,满是回忆的BGM
2020/04/09 星际争霸
php pack与unpack 摸板字符字符含义
2009/10/29 PHP
apache+php+mysql安装配置方法小结
2010/08/01 PHP
献给php初学者(入门学习经验谈)
2010/10/12 PHP
Symfony2在Nginx下的配置方法图文教程
2016/02/04 PHP
javascript静态的url如何传递
2007/05/03 Javascript
url 特殊字符 传递参数解决方法
2010/01/01 Javascript
基于Jquery的将DropDownlist的选中值赋给label的实现代码
2011/05/06 Javascript
JS跨域代码片段
2012/08/30 Javascript
JS在textarea光标处插入文本的小例子
2013/03/22 Javascript
Jquery Ajax方法传值到action的方法
2014/05/11 Javascript
删除条目时弹出的确认对话框
2014/06/05 Javascript
JavaScript中的立即执行函数表达式介绍
2015/03/15 Javascript
AngularJS转换响应内容
2016/01/27 Javascript
JavaScript中数组去除重复的三种方法
2016/04/22 Javascript
jQuery实现发送验证码并60秒倒计时功能
2016/11/25 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
2017/05/17 Javascript
AngularJS select设置默认值的实现方法
2017/08/25 Javascript
js实现无缝轮播图插件封装
2020/07/31 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
videocapture库制作python视频高速传输程序
2013/12/23 Python
python操作日期和时间的方法
2014/03/11 Python
python下10个简单实例代码
2017/11/15 Python
详解Python中的四种队列
2018/05/21 Python
Python爬虫抓取技术的一些经验
2019/07/12 Python
Django框架HttpRequest对象用法实例分析
2019/11/01 Python
Python+PyQt5实现灭霸响指功能
2020/05/25 Python
Python OpenCV实现测量图片物体宽度
2020/05/27 Python
浅谈pycharm导入pandas包遇到的问题及解决
2020/06/01 Python
Python3 ffmpeg视频转换工具使用方法解析
2020/08/10 Python
萨克斯第五大道精品百货店: Saks Fifth Avenue
2017/04/28 全球购物
Desigual德国官网:在线购买原创服装
2018/03/27 全球购物
为数据库创建索引都需要注意些什么
2012/07/17 面试题
离婚协议书范本(通用篇)
2014/11/30 职场文书
教师节主持词开场白
2015/05/29 职场文书
读《儒林外史》有感:少一些功利,多一些真诚
2020/01/19 职场文书