经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » jQuery » 查看文章
jQuery 源码分析(十二) 数据操作模块 html特性 详解
来源:cnblogs  作者:大沙漠  时间:2019/10/18 8:49:51  对本文有异议

jQuery的属性操作模块总共有4个部分,本篇说一下第1个部分:HTML特性部分,html特性部分是对原生方法getAttribute()和setAttribute()的封装,用于修改DOM元素的特性的

jQuery的静态方法含有如下API:

  • $.attr(elem, name, value)  ;设置或读取html属性,该方法有三种用法:

                    ·$.attr(elem,name,null)       ;如果value为null则调用jQuery.removeAttr(elem, name)删除该属性
                    ·$.attr(elem,name,value)    ;设置elem元素的name属性值为value。
                    ·$.attr(elem,name)              ;获取elem元素的name属性

  • $.removeAttr(elem, name)  ;从DOM元素elem上移除name属性,name可以是单个字符串,也可以是空格分隔的多个html属性。对于应布尔属性会同步设置对应的DOM属性为false。

jQuery/$ 实例方法(可以通过jQuery实例调用的):

  • attr(name, value)           ;移除、设置html属性,有以下方法

      ·attr(obj)             ;参数1是对象时                             ;access()函数中验证 表示一次性设置多个属性
      ·attr(name,value)       ;为每个匹配元素设置一个HTML属性                  ;value可以是一个函数,取值为返回值,也可以为null时表示删除该属性    
      ·attr(name,NULL)         ;参数2为NULL时表示删除所有匹配元素的name特性,间接调用removeAttr()
      ·attr(name)              ;参数1是字符串时,参数2未指定或者设置为false    ;表示获取第一个匹配元素的HTML属性值。

  • removeAttr(name)                    ;移除每一个匹配元素的一个或多个HTML属性,name是要是移除的html属性,多个可以用空格分隔

举个栗子:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
  7. </head>
  8. <body>
  9. <a>链接</a>
  10. <button>淘宝</button> <!--点击后a标签将导航到淘宝-->
  11. <button>百度</button> <!--点击后a标签将导航到百度-->
  12. <button>移除</button> <!--点击后a标签将取消导航-->
  13. <script>
  14. let a = document.getElementsByTagName('a')[0], //获取a标签的引用
  15. b1 = document.getElementsByTagName('button')[0], //淘宝按钮的引用
  16. b2 = document.getElementsByTagName('button')[1], //百度按钮的引用
  17. b3 = document.getElementsByTagName('button')[2]; //移除按钮的引用
  18. b1.addEventListener('click',function(){
  19. $.attr(a,'href','http://www.taobao.com'); //通过jQuery的静态方法设置href属性
  20. })
  21. b2.addEventListener('click',function(){
  22. $('a').attr('href','http://www.baidu.com') //通过jQuery的实例方法设置href属性
  23. })
  24. b3.addEventListener('click',function(){
  25. $("a").removeAttr('href') //移除href属性
  26. })
  27. </script>
  28. </body>
  29. </html>

渲染的页面如下:

 此时对应的DOM结构如下:

  当我们点击淘宝按钮后页面变为了如下:

DOM修改了这样子:

此时点击这个a标签将链接到淘宝网,然后我们点击百度,链接会链接到百度去的,最后点击移除时,该a标签又会变为初始化的状态。这就是jQuery的html特性操作

 

源码分析


 $.attr和$.removeAttr实现如下:

  1. jQuery.extend({
  2. attr: function( elem, name, value, pass ) { //设置或读取html属性,是对原生方法getAttribute()和setAttribute()的简化
  3. var ret, hooks, notxml,
  4. nType = elem.nodeType;
  5. // don't get/set attributes on text, comment and attribute nodes
  6. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { //如果elem为空 或者是文本、注释、属性节点
  7. return; //直接返回,不接着处理
  8. }
  9. if ( pass && name in jQuery.attrFn ) {
  10. return jQuery( elem )[ name ]( value );
  11. }
  12. // Fallback to prop when attributes are not supported
  13. if ( typeof elem.getAttribute === "undefined" ) { //如果不支持方法getAttribute
  14. return jQuery.prop( elem, name, value ); //则调用对应的DOM属性
  15. }
  16. notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); //判断elem是否不是xml文档元素
  17.  
  18. // All attributes are lowercase
  19. // Grab necessary hook if one is defined
  20. if ( notxml ) {
  21. name = name.toLowerCase();
  22. hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
  23. }
  24. if ( value !== undefined ) { //如果传入了参数value,表示是设置值
  25.  
  26. if ( value === null ) { //值是null,则移除该name属性
  27. jQuery.removeAttr( elem, name );
  28. return;
  29. } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { //优先调用对应的修正对象的修正方法set()
  30. return ret;
  31. } else {
  32. elem.setAttribute( name, "" + value ); //否则调用原生方法setAttribute()设置html属性
  33. return value;
  34. }
  35. } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { //如果未传入参数value,优先调用对应的修正对象的修正方法get()
  36. return ret;
  37. } else {
  38. ret = elem.getAttribute( name ); //否则调用原生方法getAttrubute()读取html属性。
  39.  
  40. // Non-existent attributes return null, we normalize to undefined
  41. return ret === null ?
  42. undefined :
  43. ret;
  44. }
  45. },
  46. removeAttr: function( elem, value ) { //从DOM元素上移除一个或多个html属性,多个html属性用空格分隔。是对removeAttribute的封装和扩展。
  47. var propName, attrNames, name, l,
  48. i = 0;
  49. if ( value && elem.nodeType === 1 ) { //如果设置了value参数 且 elem是一个元素节点
  50. attrNames = value.toLowerCase().split( rspace ); //执行后attrNames是一个数组,保存了要移除的属性名:比如:Array [ "id", "name" ] rspace = /\s+/,
  51. l = attrNames.length; //需要移除的属性的个数
  52.  
  53. for ( ; i < l; i++ ) { //遍历数组attrNames,逐个移除html属性。
  54. name = attrNames[ i ]; //name是要移除的属性名
  55.  
  56. if ( name ) {
  57. propName = jQuery.propFix[ name ] || name; //如果属性名name需要修正,则修正属性
  58.  
  59. // See #9699 for explanation of this approach (setting first, then removal)
  60. jQuery.attr( elem, name, "" ); //先将html属性设置为空字符串,以解决Webkit内核浏览器不能
  61. elem.removeAttribute( getSetAttribute ? name : propName ); //调用原生方法removeAttribute删除对应的属性,如果jQuery.support.getSetAttribute为true则删除name属性,如果为false,表示在IE6、7下则删除特殊属性。
  62.  
  63. // Set corresponding property to false for boolean attributes
  64. if ( rboolean.test( name ) && propName in elem ) { //对应布尔属性,同步设置对应的DOM属性为false
  65. elem[ propName ] = false;
  66. }
  67. }
  68. }
  69. }
  70. },
  71. /**/
  72. })

对于jQuery实例来说,它调用了不同的工具函数,最后还是执行上面讲解的静态方法的,如下:

  1. jQuery.fn.extend({
  2. attr: function( name, value ) { //移除、设置html属性
  3. return jQuery.access( this, name, value, true, jQuery.attr ); //调用了jQuery.access工具函数,参数5传入了jQuery.attr
  4. },
  5. removeAttr: function( name ) { //移除html属性
  6. return this.each(function() { //通过each函数方法,依次执行jQuery.removeAttr()
  7. jQuery.removeAttr( this, name );
  8. });
  9. },
  10. /**/
  11. })

由于jQuery中的特性、DOM属性和样式操作的函数参数可以是差不多的,jQuery就定义了一个access函数,为.attr()、.prop()、.css()提供支持,这样我们通过jQuery实例设置特性、属性和样式时可以传入的参数类型,例如:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
  7. </head>
  8. <body>
  9. <a>链接</a>
  10. <script>
  11. $('a').attr('href','http://www.cnblogs.com') //参数2是个字符串
  12. $('a').attr('href',()=>'http://www.cnblogs.com') //参数2还是是个函数
  13. $('a').attr({href:'http://www.cnblogs.com'}) //也可以传入一个对象
  14. </script>
  15. </body>
  16. </html>

我们传入不同的参数,都可以实现设置特性的效果,这就是$.access的作用,$.access的源码实现如下:

  1. jQuery.extend({
  2. access: function( elems, key, value, exec, fn, pass ) { //为集合中的元素设置一个或多个属性值,或者读取第一个元素的属性值
  3. var length = elems.length;
  4. // Setting many attributes
  5. if ( typeof key === "object" ) { //如果key是对象,表示要设置多个属性,则遍历该对象循环执行.access函数
  6. for ( var k in key ) {
  7. jQuery.access( elems, k, key[k], exec, fn, value );
  8. }
  9. return elems;
  10. }
  11. // Setting one attributes
  12. if ( value !== undefined ) { //如果参数value不是undefined,表示要设置单个属性
  13. // Optionally, function values get executed if exec is true
  14. exec = !pass && exec && jQuery.isFunction(value); //修正exec参数。如果没有传入pass参数或者该参数值是false,且参数exec为true,且value是函数则设置exec为true,否则exec为false。
  15.  
  16. for ( var i = 0; i < length; i++ ) {
  17. fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); //遍历元素集合elems,为每个元素调用回调函数fn
  18. }
  19. return elems; //遍历完成后返回元素elems。以支持链式操作
  20. }
  21. // Getting an attribute
  22. return length ? fn( elems[0], key ) : undefined; //当value参数为空,且元素集合elems不为空则获取第一个匹配元素相关的信息,即执行fn函数
  23. },
  24. /**/
  25. })

 writer by:大沙漠 QQ:22969969

之后的DOM属性和样式操作都会借用access这个工具方法的。

原文链接:http://www.cnblogs.com/greatdesert/p/11670682.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号