【jquery源码二】$选择器--是如何将DOM封装成jquery对象的②

前言:前面一篇已经看过$是如何封装jQuery对象的,可以简单的概述为,把DOM对象放在了属性名为0、1、2....下面,然后给jQuery添加了context,length,selector属性,还有一些实例出来的方法。

【jquery源码二】$选择器--是如何将DOM封装成jquery对象的①

【jquery源码】目录表。

这篇文章来说说jQuery是如何实现众多选择器效果的。

一、基本架构。

1、先来看看几种选择器的使用

    ①、创建html: $('<div>')、$('<div>1</div><div></div>')、$('<div>hello')

    ②、常规选择: $('#id')、$('.class')、$('div')

    ③、复杂选择: $('.class',$(document))、$('.class',document)、$('#id .class')、$('div.class') 、$('input[type="text"]')

    ④、将DOM转换成jQueryd对象:$(document)、$(this)、$(DOM)

    ⑤、特殊选择:$(function(){}),$([]),$({})

2、再看看这几种选择在init()都是走哪

(function(window,undefined){  
    var rootjQuery = jQ(document),
	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
		
    var jQuery = function(selector){  
	return new jQuery.fn.init(selector);  
    };  
    jQuery.fn = jQuery.prototype = {  
	jquery:'2.0.3',       //jquery版本号信息
	constructor: jQuery,  //添加构造器属性
	length:0,	      //初始length属性
	selector:'',	      //初始selector属性
	init: function(selector, context, rootjQuery){   
	    var match, elem;

	    // 如果是: $(""), $(null), $(undefined), $(false)  直接return jQuery对象
	    if ( !selector ) {  return this; }
			
	    if( typeof selector === "string"){  //判断selector是否是string类型

		if(selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3){
		    //判断是否是 $('<div>')、$('<div>1</div><div></div>')
		}else{
		    /*
		        selector是string类型的,
			除了$('<div>')、$('<div>1</div><div></div>'),都会走一次这里
		    */
		}
		
		if( match[1] && (match[1] || !context) ){   
				
		    if( match[1] ){    
			//$('<div>')、$('<div>1</div><div></div>')
		    }else{
			//$('#id')
		    }
			
		}else if(!context || context.jquery){
		    //$('.class')、$('div')、$('<div>hello')
		    //$('.class',$(document))、$('#id .class')、$('div.class') 、$('input[type="text"]')
		}else{
		    //$('div',document)
		}
		
	    }else if( selector.nodeType ){    //判断selector是DOM节点对象
		//$(document)、$(this)、$(DOM)
	    }else if( jQuery.isFunction(selector )){   //判断selector是函数
		//$(function(){})
	    }
		
	    if(selector.selector !== undefined ){
		//特殊处理已经是jquery对象的$($('#id'))
	    }  
		  
	    return jQuery.makeArray( selector, this );   //$([]),$({})
	    }
    }
	
    jQuery.fn.init.prototype = jQuery.fn;  
	
    window.$ = window.jQuery = jQuery;    	
})( window ); 

二、代码解析。

1、选择器参数是string类型的

if( typeof selector === "string"){  //判断selector是否是string类型

    if(selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3){
	// $('<div>') -> match = [null, '<div>', null];
	// $('<div>1</div><div>2</div>') -> match = [null, '<div>1</div><div>2</div>', null]
	match = [ null, selector, null ];
    }else{
	match = rquickExpr.exec( selector );
	//$('#div') -> match=['#div', undefined, 'div'] 
	//$('<div>hello') -> match=['<div>hello','<div>', undefined] 
	//$('.class')、$('div')、$('#id .class')、$('div.class') 、$('input[type="text"]') -> match = null
    }
		
    if( match[1] && (match[1] || !context) ){   
				
	if( match[1] ){    
		context = context instanceof jQuery ? context[0] : context;
	        jQuery.merge( this, jQuery.parseHTML(  
		    match[1],
		    context && context.nodeType ? context.ownerDocument || context : document,
		    true
		));
		//$('<div>',{title:'hi',html:'abcd',css:{background:red}}); 
		if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {  
                    // 添加属性只支持单标签,而且context是对象自变量(json格式)
						
		    for ( match in context ) {    //对第二个参数对象自变量进行for in 循环。
		        //如果是this[match]是jQuery方法的话就调用方法,如果不是的话就用attr进行属性添加 
		        if ( jQuery.isFunction( this[ match ] ) ) {   //$().html、$().css  
			    this[ match ]( context[ match ] );   //$().html('abcd')
		        } else {
			    this.attr( match, context[ match ] );   //通过attr进行添加
		        }
		    }
		}
		return this;
        }else{	//$('#id')   match=['#id',null,'id'] 
	    elem = document.getElementById( match[2] );   
	    if ( elem && elem.parentNode ) {
		this.length = 1;
		this[0] = elem;
	    }
	    this.context = document;
	    this.selector = selector;
	    return this;
	}
			
    }else if(!context || context.jquery){          
        //$('.class')、$('div')、$('<div>hello')
      //$('.class',$(document))、$('#id .class')、$('div.class') 、$('input[type="text"]')
      //!context有没实参(没有实参的话进入这里) || 判断context是不是jquery对象(通过查看有没有jquery版本号属性) 

      return ( context || rootjQuery ).find( selector );   //$(document).find(selector)
  }else{
//$('div',document)return this.constructor( context ).find( selector ); //jQuery(document).find('div');    }}

2、选择器参数是DOM节点的

else if( selector.nodeType ){	//是DOM节点对象的话都有nodeType属性
    //$(document)、$(this)、$(DOM)
    this.context = this[0] = selector;
    this.length = 1;
    return this;
}

3、选择器参数是function()

else if( jQuery.isFunction(selector )){
    //$(function(){})
    return rootjQuery.ready( selector );
}

4、选择器是jQuery对象

if(selector.selector !== undefined ){
    //特殊处理已经是jquery对象的$($('#id'))
    this.selector = selector.selector;
    this.context = selector.context;
}  

5、特殊参数$([]),$({})

return jQuery.makeArray( selector, this );   //$([]),$({})

6、合并

(function(window,undefined){  
	var rootjQuery = jQ(document),
		rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
		
	var jQuery = function(selector){  
		return new jQuery.fn.init(selector);  
	};  
	jQuery.fn = jQuery.prototype = {  
		jquery:'2.0.3',       //jquery版本号信息
		constructor: jQuery,  //添加构造器属性
		length:0,			  //初始length属性
		selector:'',		  //初始selector属性
		init: function(selector, context, rootjQuery){   
			var match, elem;

			// 如果是: $(""), $(null), $(undefined), $(false)  直接return jQuery对象
			if ( !selector ) {  return this; }
			
			if( typeof selector === "string"){  //判断selector是否是string类型

				if(selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3){
					// $('<div>') -> match = [null, '<div>', null];
					// $('<div>1</div><div>2</div>') -> match = [null, '<div>1</div><div>2</div>', null]
					match = [ null, selector, null ];
				}else{
					match = rquickExpr.exec( selector );
					//$('#div') -> match=['#div', undefined, 'div'] 
					//$('<div>hello') -> match=['<div>hello','<div>', undefined] 
					//$('.class')、$('div')、$('#id .class')、$('div.class') 、$('input[type="text"]') -> match = null
				}
		
				if( match[1] && (match[1] || !context) ){   
				
					if( match[1] ){    
						context = context instanceof jQuery ? context[0] : context;
						jQuery.merge( this, jQuery.parseHTML(  
							match[1],
							context && context.nodeType ? context.ownerDocument || context : document,
							true
						) );
						//$('<div>',{title:'hi',html:'abcd',css:{background:red}}); 
						if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {  // 添加属性只支持单标签,而且context是对象自变量(json格式)
						
							for ( match in context ) {    //对第二个参数对象自变量进行for in 循环。
								//如果是this[match]是jQuery方法的话就调用方法,如果不是的话就用attr进行属性添加 
								if ( jQuery.isFunction( this[ match ] ) ) {   //$().html、$().css  
									this[ match ]( context[ match ] );   //$().html('abcd')
								} else {
									this.attr( match, context[ match ] );   //通过attr进行添加
								}
							}
						}
						return this;
					}else{	//$('#id')   match=['#id',null,'id'] 
						elem = document.getElementById( match[2] );   
						if ( elem && elem.parentNode ) {
							this.length = 1;
							this[0] = elem;
						}
						this.context = document;
						this.selector = selector;
						return this;
					}
			
				}else if(!context || context.jquery){  //$('div',$(document))
					//!context有没实参(没有实参的话进入这里) || 判断context是不是jquery对象(通过查看有没有jquery版本号属性) 
					return ( context || rootjQuery ).find( selector );   //$(document).find(selector)
				}else{
					//$('div',document)
					return this.constructor( context ).find( selector );   //jQuery(document).find('div');
				}
		
			}else if( selector.nodeType ){	//是DOM节点对象的话都有nodeType属性
				//$(document)、$(this)、$(DOM)
				this.context = this[0] = selector;
				this.length = 1;
				return this;
			}else if( jQuery.isFunction(selector )){
				//$(function(){})
				return rootjQuery.ready( selector );
			}
		
			if(selector.selector !== undefined ){
				//特殊处理已经是jquery对象的$($('#id'))
				this.selector = selector.selector;
				this.context = selector.context;
			}  
		  
			return jQuery.makeArray( selector, this );   //$([]),$({})
		}
	}
	
	jQuery.fn.init.prototype = jQuery.fn;  
	
	window.$$ = window.jQuery = jQuery;    	
})( window ); 


猜你喜欢

转载自blog.csdn.net/w390058785/article/details/80895546
今日推荐