`
adamed
  • 浏览: 183805 次
社区版块
存档分类
最新评论

jQuery源码历代记3

 
阅读更多

 

前面讲解过了jQuery构造器的each方法,并顺道将jQuery的工具方法jQuery.each()也讲解了一下。

下面继续讲解jQuery 1.01构造器中的index方法,先上代码: 

 

 

index : function( obj ) {
    var pos = -1;
    this.each( function( i ) {
              if ( this == obj ) pos = i;
    } );
    return pos;
}
 

 

 

 这段代码非常简单,就是通过each方法遍历当前jQuery实例对象属性并与obj进行判断若相同则返回该属性的索引值。

 请注意:在jQuery1.4之后对该方法进行了补充,具体补充内容在讲解到1.4时再介绍。 

这里还要说明的是在jQuery1.2版本之后,将这种遍历数组比较对象的方法重新抽象出一个工具方法:jQuery.inArray();

请看代码:

 

inArray: function( elem, array ) {
   for ( var i = 0, length = array.length; i < length; i++ )
   // Use === because on IE, window == document
   if ( array[ i ] === elem ){
         return i;
    }
     return -1;
}
 

 

 代码内容比较简单没啥可解释的了。

正因为在jQuery 1.2之后抽象出来这个工具方法所以,jQuery 1.2中构造器中的index方法改写成

 

index: function( elem ) {
   var ret = -1;
   // Locate the position of the desired element
    return jQuery.inArray(
          // If it receives a jQuery object, the first element is used
          elem && elem.jquery ? elem[0] : elem , this );
}
 

好了,index就介绍到这里,可以看出jQuery核心最重要的一个思想就是以类似于数组的方式存储jQuery的各个属性。

//***************************这是重要的分界线**********************

下一个要出场的是重量级方法:attr

对于attr方法有几个重载实现,我们将分别给与说明。根据以往讲解重要方法的经验先奉献上的是API中的描述:

attr的实现之一:.attr( attributeName )

 

Description: Get the value of an attribute for the first element in the set of matched elements. 
The .attr() method gets the attribute value for only the first element in the matched set. To get the value for each element individually, use a looping construct such as jQuery's .each() or .map() method. 
 

这里明确说明attr仅对匹配对象集合的第一个元素起作用,为了帮助理解我们看下下面的代码:

<p id="p1">element1</p><p id="p2">element2</p>

如果执行$("p").attr("id");则将返回p1。

 

attr的实现之二:.attr( attributeName, value ) 

attributeName  The name of the attribute to set.

value  A value to set for the attribute.

attr的实现之三:.attr( map )

map  A map of attribute-value pairs to set.

Description: Set one or more attributes for the set of matched elements. 

举例:

html内容:

<img id="greatphoto" src="brush-seller.jpg" alt="brush seller" />

JS内容:

$('#greatphoto').attr('alt', 'Beijing Brush Seller');

将修改img的属性alt为:Beijing Brush Seller

$('#greatphoto').attr('title', 'Photo by Kelly Clark');

将为img添加一个新的属性title

如果想同时做上述2个动作则:

$('#greatphoto').attr({

    alt: 'Beijing Brush Seller',

    title: 'photo by Kelly Clark'

});

请注意如果想修改class属性则只能使用最后一种方式。 

//****************************讲解代码的分割线**************************

我们看下attr方法的代码:

 

attr : function( key , value , type ) {
   // Check to see if we're setting style values
  return key.constructor != String || value != undefined ? this.each( function() {
         // See if we're setting a hash of styles
          if ( value == undefined ){
          // Set all the styles
                for ( var prop in key ){
                       jQuery.attr( type ? this.style : this , prop , key[prop] );
                 }
                // See if we're setting a single key/value style
           } else{
                  jQuery.attr( type ? this.style : this , key , value );
           }
    } ) :
    // Look for the case where we're accessing a style value
  jQuery[ type || "attr"]( this[0] , key );
}
 

 

 让我们分析一下这段代码:

首先在jQuery的构造器中attr方法允许传入3个参数,而根据API中的描述attr最多可以传入2个参数而第3个参数是做什么用的呢?

请看最后一行:jQuery[ type || "attr"]( this[0] , key ); 这里如果向该方法中传入第3个参数则会调用jQuery[type]方法,所以说第3个参数为jQuery内部使用的且只能传递字符串并且字符串只能是jQuery工具类的方法名。

这个地方为什么是this[0]呢? “Get the value of an attribute for the first element in the set of matched elements.”还记得吗~~

讲解完参数我们看下实现的代码。整个代码就只有一句,一个return就搞定了,但在return中进行了一些判断:

key.constructor != String || value != undefined 说明如果传递的第一个参数不是字符串(对应attr( map )这种情况)或者传递的第2个参数不为空则进入this.each()部分,否则直接执行jQuery[ type || "attr"]( this[0] , key );

我们用实例分析:

$('#greatphoto').attr({

    alt: 'Beijing Brush Seller',

    title: 'photo by Kelly Clark'

});

在执行该方法时首先$('#greatphoto')得到了一个jQuery的结果集,当然上面的例子因为是使用了id选择器,所以结果集中只有一个元素。

拿到结果集后在结果集上执行attr方法,所以需要对结果集进行遍历,使用的就是前面刚介绍过的each方法。

  if ( value == undefined ){

           for ( var prop in key ){

                 jQuery.attr( type ? this.style : this , prop , key[prop] );

            }

   }

这句是在遍历每一个对象时首先判断是否在传递了key的同时传递了value。

如果是:$("p").attr({title:'ptitle',class:'pClass'});

这种形式的调用时遍历{title:'ptitle',class:'pClass'}为每一个P设置title和class属性。

如果是:如果是:$("p").attr("title","abc");

则调用    jQuery.attr( type ? this.style : this , key , value );

如果key为字符串,value还为空则属于$("p").attr("id");这种调用方式。

则执行: jQuery[ type || "attr"]( this[0] , key );

//****************这是可重要,可重要的分界线***************

现在的重点就是看下jQuery的工具方法:attr的定义:

 

attr : function( elem , name , value ) {
  var fix = {
     "for" : "htmlFor",
     "class" : "className",
      "float" : "cssFloat",
       innerHTML : "innerHTML",
        className : "className",
       value : "value",
        disabled : "disabled"
  };

   if ( fix[ name ] ) {
       if ( value != undefined ) elem[ fix [ name ] ] = value;
          return elem[ fix [ name ] ];
    } else if ( elem.getAttribute ) {
          if ( value != undefined ) elem.setAttribute( name , value );
           return elem.getAttribute( name , 2 );
    } else {
          name = name.replace( /-([a-z])/ig , function( z , b ) {
                           return b.toUpperCase();
                        });
        if ( value != undefined ) elem[ name ] = value;
              return elem[ name ];
    }
}
 

 一开始有一个fix的对象,里面将一些值转换成了字符串。将class转换为js调用class时需要使用的className。为什么要这样呢?

jQuery的API中有一个很重要的提示:

Note: Attribute values are strings with the exception of a few attributes such as value and tabindex. 

好吧,英文看不懂的童鞋请google翻译吧。

jQuery的attr工具方法不仅仅用来对DOM属性进行复制也肩负着修改DOM css属性的作用。

看这个代码其实很简单,首先判断待修改的属性名是否属于“需修正的属性”如果是则使用修正后的属性名进而对该属性进行赋值。

如果不属于待修正的属性则直接调用getAttrbute进行修改(这里的第2个参数那个数值2没用任何作用,怀疑是bug)

最下面的else就是用来匹配css的了。(哭了,css一直是我的死穴,看不懂直接飘过吧。。。。)

综上我们得出结论就是jQuery的attr工具方法的作用就是在elem上找到name属性并值赋值为value。

//***************************这是重要的分界线**********************

attr方法在后面的讲解中还会重复出现哦,并且由于这是jQuery体系中非常非常重要的一个基础方法,所以在jQuery升级的过程中几乎每一个版本都会对其进行重构哦。

好了,下面我们讲解下一个方法:css

 

css : function( key , value ) {
        return this.attr( key , value , "curCSS" );
}
 

从代码就可以看出构造器的css方法其实就是attr方法的style属性简化版。

其中用到了attr的第3属性哦,还记得此属性的作用吧:

直接调用jQuery.curCSS();

 

curCSS : function( elem , prop , force ) {
   var ret;
   if ( !force && elem.style[prop] ) {
         ret = elem.style[prop];
    } else if ( elem.currentStyle ) {
        var newProp = prop.replace( /\-(\w)/g ,  function( m , c ) {
                             return c.toUpperCase()
                         });
          ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
   } else if ( document.defaultView && document.defaultView.getComputedStyle ) {
          prop = prop.replace( /([A-Z])/g , "-$1" ).toLowerCase();
          var cur = document.defaultView.getComputedStyle( elem , null );
          if ( cur )
              ret = cur.getPropertyValue( prop );
         else if ( prop == 'display' )
               ret = 'none';
         else
                jQuery.swap( elem ,{display : 'block'} ,function() {
                       ret = document.defaultView.getComputedStyle( this , null )
                                   .getPropertyValue( prop );
           });
    }
  return ret;
}
 

这个方法呢~~就是把css属性换成js写法background-color准换成backgroundColor。

css我是不熟悉的,等待高人补充吧。诶。。。后台转前台的人伤不起啊。。。。

//*********************************再次出现一个重要的分割线***************************

下面是我非常常用的一个方法text

照例先看下API中对于此方法的描述

Description: Get the combined text contents of each element in the set of matched elements, including their descendants. 

 text()方法可以处理HTML和XML文档,例如:

HTML文档:

<div class="demo-container">

<div class="demo-box">Demonstration Box</div>

<ul>

<li>list item 1</li>

<li>list <strong>item</strong> 2</li>

</ul>

</div>

JS文档执行:$('div.demo-container').text()

得到的结果为:

Demonstration Box list item 1 list item 2

 //*********************************一个重要的分割线***************************

text另一个重载方法为:

.text( textString )

 

Description: Set the content of each element in the set of matched elements to the specified text.
 

 调用:$('div.demo-container').text('<p>This is a test.</p>');时页面效果为:<div class="demo-container">

&lt;p&gt;This is a test.&lt;/p&gt;

</div>

jQuery会自动将<等特殊字符进行转码。

 //*******************************讲解代码的分割线**************************

让我们看下代码:

 

text : function( e ) {
  e = e || this;
   var t = "";
   for ( var j = 0; j < e.length; j++ ) {
        var r = e[ j ].childNodes;
       for ( var i = 0; i < r.length; i++ ){
              if ( r[ i ].nodeType != 8 ){
                     t += r[ i ].nodeType != 1 ? r[ i ].nodeValue : jQuery.fn.text( [ r [ i ] ] );
                  }
        }
  }
  return t;
}
 

 

一个功能比较简单的代码,代码中的t就是返回的字符串信息。由于text会将DOM元素的子元素文本也包含进返回的信息中。所以代码中有一个递归的调用。

其中DOM的nodeType包含如下信息:

元素类型节点类型

元素element 1
属性attr 2
文本text 3
注释comments 8
文档document 9

  t += r[ i ].nodeType != 1 ? r[ i ].nodeValue : jQuery.fn.text( [ r [ i ] ] );的含义是:

首先判断当前节点是否为元素节点,如果是则进行递归。如果不是则取出nodeValue添加进t字符串中。

请大家注意一点,从上面的代码我们可以看出我们根本无法实现$('div.demo-container').text('<p>This is a test.</p>');这种方式的调用。我们看下jQuery 1.1版本时text代码的变化:

 

text : function( e ) {
    if ( typeof e == "string" ){
        return this.empty().append( document.createTextNode( e ) );
    }
    var t = "";
    jQuery.each( e || this ,function() {
        jQuery.each( this.childNodes ,  function() {
            if ( this.nodeType != 8 )
                t += this.nodeType != 1 ? this.nodeValue : jQuery.fn.text( [this] );
        });
    });
    return t;
}
 

 

从代码中我们看出变化的内容下半部分主要是将迭代变更为使用jQuery.each来实现增加复用性。

上半部分中添加了如果参数为字符串则先清空当前节点而后在当前节点下创建文本节点的代码。当然这段代码还是有一些局限性的。

 还有一个bug是如果我们这样设置:

var str = new String("<p>");

console.log(typeof str == "string");

我们可以看到结果是false,所以新的方法一般会用如下代码进行验证:

var str = new String("<p>");

var str1 = "a";

console.log(str.constructor == String);

console.log(str1.constructor == String);

执行后我们可以看出2个验证均返回true。

到了jQuery 1.2以后这句有些问题的代码变更为:

 

if ( typeof text != "object" && text != null )
       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
 

含义将来再说。嘿嘿。。

 

//**************************传送门的分割线******************

我们回到jQuery 1.0是的代码:jQuery.fn.text( [ r [ i ] ] );

这一句中的jQuery.fn.text为什么是调用自身呢?

我们在最开始的代码中可以看到:

jQuery.fn = jQuery.prototype = {

jquery : "$Rev: 509 $",

... ..... ....

所以调用jQuery.fn.text就是调用jQuery.prototype.text所以就是调用本身即迭代调用。

 

 

分享到:
评论

相关推荐

    jQuery源码 jQuery源码 jQuery源码

    jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码jQuery源码...

    JQuery源码详细中文注释_Jquery源码分析_

    《jQuery源码深度解析》 jQuery,作为一款广泛使用的JavaScript库,因其简洁的API和强大的功能,深受开发者喜爱。本文将深入探讨jQuery 1.2.6版本的源码,结合其中的中文注释,帮助读者理解其内部机制,提升...

    Jquery源码分析 源码

    《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。深入理解其源码对于提升JavaScript编程技能和优化前端性能至关重要。本文将从核心概念、设计...

    jQuery源码分析系列.pdf

    ### jQuery源码分析系列知识点概览 #### 一、总体架构与核心概念 - **前言开光**:介绍分析jQuery源码的目的和价值,强调通过深入研究源码,可以学习到先进的设计理念和实践技巧。 - **总体架构**:解析jQuery的...

    jquery源码分析

    jquery源码分析,包括入口技术,选择器入口,以及在选择器使用的时候需要注意的优化思路

    jquery源码,3.7.0版本

    jquery源码,3.7.0版本

    Head First jquery源码

    《Head First jQuery源码》是一本深入解析jQuery库的书籍,其内容主要涵盖了jQuery的核心功能、设计理念以及实现机制。jQuery是JavaScript的一个库,它极大地简化了网页中的DOM操作、事件处理、动画效果以及Ajax交互...

    jquery源码框架解读

    3. **动画效果**:jQuery的动画功能强大,包括`.animate()`, `.fadeIn()`, `.slideUp()`等。它们基于CSS属性的变化实现平滑的过渡效果。jQuery还提供了一些实用工具函数,如`.show()`, `.hide()`, `.toggle()`等,...

    jQuery源码+中文详细注解

    ### jQuery源码+中文详细注解 #### 一、引言 本文档是对jQuery源码进行中文注解的详细介绍,旨在帮助广大前端开发者更深入地理解jQuery的核心逻辑和技术要点。通过对核心部分的逐行注解,可以更好地掌握jQuery的...

    Head First jQuery源码

    3. **DOM操作**:jQuery提供了丰富的API用于操作DOM,如`append()`, `prepend()`, `remove()`等。源码中,你可以了解这些方法如何与DOM树交互。 4. **事件处理**:jQuery封装了事件处理,如`click()`, `mouseover()...

    jquery源码(1.4)

    jquery最新源码jquery最新源码jquery最新源码

    jQuery源码分析-插件

    jQuery源码分析-插件

    jQuery源码详细分析中文注释

    《jQuery源码详细分析中文注释》是一份深入解析jQuery库源码的宝贵资源,它为开发者提供了理解这个广泛使用的JavaScript库内部工作机制的机会。jQuery以其简洁的API和强大的功能深受前端开发者的喜爱,但其背后的...

    jQuery源码分析视频教程

    jQuery源码分析视频教程总计116课,按照jquery每个区段实现的内容,精确地讲解源码中是怎么实现我们开发中用到的jquery得方法的

    jQuery源码分析系列中文PDF版

    资源名称:jQuery源码分析系列 中文PDF版内容简介:jQuery凭借简洁的语法和跨平台的兼容性,极大地简化了Javascript开发开发人员遍历HTML文档、操作DOM、处理事件、执行动画和开发Ajax的操作。其独特而又优雅...

    jquery api, jquery ui api, jquery源码分析

    **jQuery API** jQuery 是一款广泛使用的 JavaScript 库,它的出现极大地简化了网页的 ...通过学习jQuery API、jQuery UI API以及源码分析,开发者不仅可以提升开发效率,还能编写出更高效、更优雅的JavaScript代码。

    jQuery 源码+实例+注释

    **jQuery 源码分析与实例详解** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了 JavaScript 的 DOM 操作、事件处理、动画制作以及 AJAX 交互。本教程旨在通过源码解析、实例演示和详细注释,帮助新手快速...

    jquery 源码分析

    Sizzle选择器引擎是jQuery的一大亮点,它实现了对CSS1至CSS3选择器的支持。Sizzle的工作原理是将CSS选择器解析为一系列的测试规则,然后应用到DOM树上,找到匹配的元素。通过这个引擎,jQuery能快速准确地定位页面中...

    jQuery源码解读

    在源码解读中,我们可以看到jQuery的设计思路和实现机制。 首先,jQuery的核心设计是基于JavaScript的闭包特性,以避免命名冲突。整个jQuery库被包裹在一个立即执行的匿名函数中,这样可以确保其中定义的所有函数和...

Global site tag (gtag.js) - Google Analytics