六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 152|回复: 0

jQuery源码学习笔记二 转

[复制链接]

升级  11.33%

17

主题

17

主题

17

主题

秀才

Rank: 2

积分
67
 楼主| 发表于 2013-2-7 23:44:04 | 显示全部楼层 |阅读模式
<p>前文提要,jQuery用init方法创建的,它是jQuery.fn.init的实例而非jQuery的实例,后期会用jQuery.fn.init.<wbr>prototype =<wbr> <wbr>jQuery.fn;把相应的能力从jQuery.prototype搬运到jQuery.fn.init.prototype上。因此,init之后,作者就放心地往jQuery的原型添加方法。而这些原型更多的时候是往外调用其静态方法来工作。一开始,都是一些用于构建类数组的东西。像setArray,makeArray,size,get,pushStack等方法。</p><pre class="brush:javascript;gutter:false;toolbar:false">//@author  司徒正美|なさみ|cheng http://www.cnblogs.com/rubylouvre/  All rights reserved     //另一个复杂的方法css: function( key, value ) {// ignore negative width and height valuesif ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )value = undefined;return this.attr( key, value, "curCSS" );},   //与css与attr一样,既能读亦能写text: function( text ) {if ( typeof text !== "object" && text != null )return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );var ret = "";jQuery.each( text || this, function(){jQuery.each( this.childNodes, function(){if ( this.nodeType != 8 )ret += this.nodeType != 1 ?this.nodeValue :jQuery.fn.text( [ this ] );});});return ret;},    //把匹配的元素作出了为一个整体用参数里的标签(如果传入的是元素也会转换为标签)包起来,    //$("p").wrapAll('<div></div>') =>  <div><p>******</p><p>******</p><p>******</p></div>    //这东西应该叫wrapOutter更好wrapAll: function( html ) {if ( this[0] ) {// The elements to wrap the target aroundvar wrap = jQuery( html, this[0].ownerDocument ).clone();if ( this[0].parentNode )wrap.insertBefore( this[0] );wrap.map(function(){var elem = this;while ( elem.firstChild )elem = elem.firstChild;return elem;}).append(this);}return this;},    //相当于把匹配的元素取得其innerHTML,然后用wrapAll方法包起来    //$("p").wrapInner('<div></div>') =>  <p><div>******</div></p><p><div>******</div></p><p><div>******</div></p>   wrapInner: function( html ) {return this.each(function(){jQuery( this ).contents().wrapAll( html );});},//与上面相反,有点像outterHTML,内容外面加一层皮//$("p").wrap('<div></div>') =>  <div><p>******</p></div><div><p>******</p></div><div><p>******</p></div>wrap: function( html ) {return this.each(function(){jQuery( this ).wrapAll( html );});},</pre><p>接着下来分析append,prepend,before,after。内部实现非常复杂,先扼要类比一下已有的API吧。</p><pre class="brush:javascript;gutter:false;toolbar:false">//append:向每个匹配的元素内部追加内容。//相当于//insertAdjacentHTML("beforeEnd",htmlstr)//insertAdjacentElement("beforeEnd",dom)//insertAdjacentElement("beforeEnd",jQueryEl)//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)</pre><pre class="brush:javascript;gutter:false;toolbar:false">//prepend:向每个匹配的元素内部前置内容。//相当于//insertAdjacentHTML("afterBegin",htmlstr)//insertAdjacentElement("afterBegin",dom)//insertAdjacentElement("afterBegin",jQueryEl)//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)</pre><pre class="brush:javascript;gutter:false;toolbar:false">//before:在每个匹配的元素之前插入内容。//相当于//insertAdjacentHTML("beforeBegin",htmlstr)//insertAdjacentElement("beforeBegin",dom)//insertAdjacentElement("beforeBegin",jQueryEl)//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)</pre><pre class="brush:javascript;gutter:false;toolbar:false">//after:在每个匹配的元素之后插入内容。。//相当于//insertAdjacentHTML("afterEnd",htmlstr)//insertAdjacentElement("afterEnd",dom)//insertAdjacentElement("afterEnd",jQueryEl)//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)</pre><p>这些方法内部都调用一个叫domManip的方法,它的存在价值仅仅是为了兼容邪恶的火狐,因为火狐死活不支持IE的insertAdjacentXXX系列。</p><pre class="brush:javascript;gutter:false;toolbar:false">//@author  司徒正美|なさみ|cheng http://www.cnblogs.com/rubylouvre/  All rights reserved//主要用于返回上次覆盖了DOM元素数组      end: function() {        return this.prevObject || jQuery( [] );      },            // For internal use only.      // Behaves like an Array's method, not like a jQuery method.      push: [].push,      sort: [].sort,      splice: [].splice,      //jQuery强大的CSS选择器      find: function( selector ) {        if ( this.length === 1 ) {          var ret = this.pushStack( [], "find", selector );          ret.length = 0;          //分别为表达式,上下文,与之前获得的元素集合(它们将作为此次的搜索起点)          jQuery.find( selector, this[0], ret );          return ret;        } else {          //每次都会重新洗牌,因此必须进行压栈操作          return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){            return jQuery.find( selector, elem );          })), "find", selector );        }      },      //先复制DOM再复制其上的事件      clone: function( events ) {        // Do the clone        var ret = this.map(function(){          if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {            // IE copies events bound via attachEvent when            // using cloneNode. Calling detachEvent on the            // clone will also remove the events from the orignal            // In order to get around this, we use innerHTML.            // Unfortunately, this means some modifications to            // attributes in IE that are actually only stored            // as properties will not be copied (such as the            // the name attribute on an input).            var html = this.outerHTML;                        if ( !html ) {              var div = this.ownerDocument.createElement("div");              div.appendChild( this.cloneNode(true) );              html = div.innerHTML;            }            //将字符串转换成jQuery对象            return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];          } else            return this.cloneNode(true);        });        //许多是后面的方法,到时再说        // Copy the events from the original to the clone        if ( events === true ) {          var orig = this.find("*").andSelf(), i = 0;                    ret.find("*").andSelf().each(function(){            if ( this.nodeName !== orig[i].nodeName )              return;                        var events = jQuery.data( orig[i], "events" );                        for ( var type in events ) {              for ( var handler in events[ type ] ) {                jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );              }            }                        i++;          });        }                // Return the cloned set        return ret;      },      //如果参数是函数则用jQuery.greg,否则用jQuery.multiFiler      filter: function( selector ) {        return this.pushStack(        jQuery.isFunction( selector ) &&          jQuery.grep(this, function(elem, i){          return selector.call( elem, i );        }) ||                    jQuery.multiFilter( selector, jQuery.grep(this, function(elem){          return elem.nodeType === 1;        }) ), "filter", selector );      },      //筛选最近的元素      closest: function( selector ) {        //判断是否用于方位的        var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,        closer = 0;        //把得到元素用map进行进一步的筛选        return this.map(function(){          var cur = this;          while ( cur && cur.ownerDocument ) {            if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {              jQuery.data(cur, "closest", closer);              return cur;            }            cur = cur.parentNode;            closer++;          }        });      },      //用于反选,内部调用filter      not: function( selector ) {        if ( typeof selector === "string" )        // test special case where just one selector is passed in          if ( isSimple.test( selector ) )//如果单一的类            return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );        else          selector = jQuery.multiFilter( selector, this );        //处理NodeList        var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;        return this.filter(function() {//再回调用filter          return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;        });      },      //添加新元素,内部进行清零压栈等操作      add: function( selector ) {        return this.pushStack( jQuery.unique( jQuery.merge(        this.get(),        typeof selector === "string" ?          jQuery( selector ) :          jQuery.makeArray( selector )      )));      },      //相当于javascript1.6 Array的some方法      is: function( selector ) {        return !!selector && jQuery.multiFilter( selector, this ).length > 0;      },      //怎么这方法那么笨重?!      hasClass: function( selector ) {        return !!selector && this.is( "." + selector );      },      //基本上是用于获取元素value属性的值      //对于下拉开框,则是其innerText      //与css,attr一样,可读可写      val: function( value ) {        if ( value === undefined ) {          var elem = this[0];                    if ( elem ) {            if( jQuery.nodeName( elem, 'option' ) )              return (elem.attributes.value || {}).specified ? elem.value : elem.text;                        // We need to handle select boxes special            if ( jQuery.nodeName( elem, "select" ) ) {              var index = elem.selectedIndex,              values = [],              options = elem.options,              one = elem.type == "select-one";                            // Nothing was selected              if ( index < 0 )                return null;                            // Loop through all the selected options              for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {                var option = options[ i ];                                if ( option.selected ) {                  // Get the specifc value for the option                  value = jQuery(option).val();                                    // We don't need an array for one selects                  if ( one )                    return value;                                    // Multi-Selects return an array                  values.push( value );                }              }                            return values;            }                        // Everything else, we just grab the value            return (elem.value || "").replace(/\r/g, "");                      }                    return undefined;        }                if ( typeof value === "number" )          value += '';                return this.each(function(){          if ( this.nodeType != 1 )            return;          //处理radio的checkbox checked属性,用于返回true与false          if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )            this.checked = (jQuery.inArray(this.value, value) >= 0 ||            jQuery.inArray(this.name, value) >= 0);                    else if ( jQuery.nodeName( this, "select" ) ) {            var values = jQuery.makeArray(value);                        jQuery( "option", this ).each(function(){              this.selected = (jQuery.inArray( this.value, values ) >= 0 ||                jQuery.inArray( this.text, values ) >= 0);            });                        if ( !values.length )              this.selectedIndex = -1;                      } else            this.value = value;        });      },      //就是innerHTML      html: function( value ) {        return value === undefined ?          (this[0] ?          this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :          null) :          this.empty().append( value );      },      //与replaceNode差不多      replaceWith: function( value ) {        return this.after( value ).remove();      },      //把等于此索引值的DOM对象从jQuery对象中取出      eq: function( i ) {        return this.slice( i, +i + 1 );      },
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表