【101~194】 init( ) : 属性初始化和参数管理
框架:
行数 | 代码 | 作用 |
---|---|---|
101 | init: function( selector, context, rootjQuery ) {...} | 头尾 |
105~107 | if ( !selector ) return this; | 传入的是不正确直接返回,$(""), $(null), $(undefined), $(false) |
109~172 | if ( typeof selector === "string" ) {...} | 处理非空字符串,如$('#div1') $('.box') $('div') $('#div1 div.box'),或用来创建的$('<li>') $('<li>1</li><li>2</li>') |
174~178 | if ( selector.nodeType ) {...} | 对DOM元素进行处理,如$(this) $(document) |
182~184 | if ( jQuery.isFunction( selector ) ) {...} | 对函数进行处理,如$(function(){}) |
186~189 | if ( selector.selector !== undefined ) {...} | 处理传参为jQuery对象,如$( $( '#div1' ) ) |
191 | return jQuery.makeArray( selector, this ); | 处理数组,如json,如$([]) $({}) |
101 笔记:
**【101】init: function( selector, context, rootjQuery ) {...} **
- 在第63行,jQuery( )这个外部接口返回该构造函数。
所以,$( selector, context )的这两个参数实际上是init处理的。 - $( 'li', 'ul' ),选择ul下的li,第一个参数是要选择的元素,第二个参数是要选择元素的执行上下文。
- $( ),可传入的参数类型非常多,init会对它们进行分类处理。
【109~172】if ( typeof selector === "string" ) {...} 源码笔记:
// 传入的是一个字符串(非空),如$('#div1') $('.box') $('div') $('#div1 div.box')
// 或用来创建的$('<li>') $('<li>1</li><li>2</li>')
if ( typeof selector === "string" ) {
// 判断是否为标签
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
match = [ null, selector, null ];// 是标签的扔进match里,如$('<li>') $('<li>1</li><li>2</li>')
//match = [ null, '<li>1</li><li>2</li>', null ];
} else {// 不是标签的,如$('#div1') $('.box') $('div') $('#div1 div.box')
//$('<li>hello')也是这里
match = rquickExpr.exec( selector );// 75行的正则,rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
// 匹配标签 | 匹配#ID
} // $('#div1')------> match = [ '#div1', null, 'div1' ];
// $('<li>hello')--> match = [ '<li>hello', '<li>', null ];
// 因为子项1只匹配标签,所以hello会被忽略
// $('.box') $('div') $('#div1 div.box')这几种匹配不到match=null;
// match在$('<li>') $('<li>1</li><li>2</li>') $('#div1')情况下为真
// match = [ '<li>hello', '<li>', null ];
// match = [ null, '<li>1</li><li>2</li>', null ];处理这两种形式
if ( match && (match[1] || !context) ) {
if ( match[1] ) {//进一步判断 : if(){ $('<li>') } else { $('#div1') }
context = context instanceof jQuery ? context[0] : context;// 创建标签的第二参没啥用
// $('<li>',$(document))这样写时,第二参是jQuery对象,instanceof为真,0为document.
//而$('<li>', document)这样写时,instanceof为假,第二参为document。
jQuery.merge( this, jQuery.parseHTML(// 一参this为json,二参为数组,可合并成json
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true// 二参为根节点;三参默认为false,//true则可添加<script><\/script>
) );
//$('<li></li>',{title : 'hi',html : '1',css : {background:'red'}}).appendTo( 'ul' );处理该形式
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
// rsingleTag匹配<li></li>空标签 && 必须是一个对象字面量{}
for ( match in context ) {// 循环二参{}
// match为{}的title,html,css
if ( jQuery.isFunction( this[ match ] ) ) {// 判断是否为函数
//JQ里有html方法,所以{}里有html就会直接调用该方法
this[ match ]( context[ match ] ); //相当于this.html( );
} else {// JQ中无title方法,就直接加属性
this.attr( match, context[ match ] );
}
}
}
return this;// 创建标签的过程完毕了
//处理$('#div1')形式 match = ['#div1',null,'div1']
} else {
elem = document.getElementById( match[2] );
//一般浏览器判断elem就可知该ID的元素存不存在
if ( elem && elem.parentNode ) {//Blackberry 4.6不行只判断elem,需elem.parentNode存在才行
//一个元素只要存在必定有父级,如不存在则没有
this.length = 1;// JQ选择元素时是存成了JSON形式,只存一个时,其无length属性,手动加下
this[0] = elem;
}
this.context = document;// ID的作用上下文是document
this.selector = selector;// 存的就是这个字符串,如'#div1'
return this;// ID结束
}
// 除 $('<li>') $('#div1')之外的复杂选择
// 如 $('.box') $('div') $('#div1 div.box')
} else if ( !context || context.jquery ) {//但执行上下文不存在时,就去根节点找
//如有上下文,且是jQuery对象,就直接去context找
return ( context || rootjQuery ).find( selector );// rootjQuery为$(document)
// find()会在指定地方进行筛选
// $(document).find('ul li.box');
// 找复杂的标签是通过find()实现的
} else {// 如有上下文,又不是jQuery对象,就走该处
return this.constructor( context ).find( selector );
}
【109~172】if ( typeof selector === "string" ) {...} 备注:
1. 代码流程
有三个参数 selector 和 context, rootjQuery :
if( selector 是字符串 )
if( selector 是标签 )
扔进 match // [ null, 标签(可能内有文本), null ]
else // 不是标签,是#ID,或其他复杂 字符串
正则匹配后扔进 match // null
// [ 标签和文本, 标签(无文本), null ]
// [ #ID, null, ID ]
if( match 存在 || match[1] 不为 null,是标签 )
if( match[1] 是标签 ) // 创建标签用的
处理创建标签的第二参
将 match[1] 合并为 json
if( 是空标签 && 带标签属性 )
if( 属性中有JQ的方法,如html )
使用该方法
else
直接加属性
创建标签结束
else // 处理#ID, 这里 match = [ #ID, null, ID ]
if( 该ID在页面中存在,即 match[2] 不为 null )
给该 this 添加 length属性,并 this[0] = 该ID的元素;
#ID处理结束。
else if( 无 context || 有 context,且为JQ对象 )
找到 selector
else // 如有上下文,又不是jQuery对象
找到 selector
2. 涉及到的其他知识
-
rquickExpr.exec( selector )
正则下的 exec(), 会找到一个匹配的数组集,在正则不加g的情况下,不光会将整体匹配到,还会匹配子项。 -
创建标签时的第二参 $( '<li>', document )
第二参是指定不同环境下的根节点。
比如用 contentWindow.document 可找到 iframe 下的 document。 -
jQuery.parseHTML( )把字符串转成节点数组
如 :
var str = '<li>1</li><li>2</li>';
var arr = jQuery.parseHTML( str); // [ 'li', 'li' ]
其有3个参数:
1. 要转的数组。
2. 指定根节点,如document。
3. 布尔,默认为false。 为true时,可转script标签。
-
jQuery.merge()可对数组和json进行合并
数组和数组合并为数组。
json和数组合并为json。
var json = { 0:'a', 1:'b', length:2 };
var arr = [ 'c', 'd' ];
$.merge( json, arr ); //{ 0:'a', 1:'b', 2:'c', 3:'d', length:4 }
- jQuery( ).find()会在指定地方进行筛选
JQ有两种写法:
$( 'ul', document ).find( 'li' );
有二参,不是JQ对象,走 return context.find( selector );
相当于 jQuery( document ).find( 'li' );
$( 'ul', $( document ) ).find( 'li' );
有二参,是JQ对象,走 return this.constructor( context ).find( selector );
this.constructor ---> jQuery
所以也相当于 jQuery( document ).find( 'li' );
【174~178】if ( selector.nodeType ) {...} 源码笔记:
// 对DOM元素进行处理,如$(this) $(document)
} else if ( selector.nodeType ) {//节点类型肯定有nodeType
this.context = this[0] = selector;// 将该节点赋到json的第0个属性上,然后设置执行上下文
// 节点无父级的说法,所以上下文就是其本身
this.length = 1;// 得手动的改变下json的length。
return this;// 其实就是把所找的东西存到this,并让该this带下标、带length
【182~184】if ( jQuery.isFunction( selector ) ) {...} 源码笔记:
// 对函数处理,$(function(){}) // 函数在这里主要充当文档加载的角色
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );// 在根节点ready的情况下来调用该函数
}
【182~184】if ( jQuery.isFunction( selector ) ) {...} 备注:
// JQ中文档加载有两种写法:就是由该处实现的
$( function () {} )
$( document ).ready( function () {} )
【186~189】if ( selector.selector !== undefined ) {...} 源码笔记:
// 处理 $( $( '#div1' ) ) // 判断传的参是不是jQuery对象
if ( selector.selector !== undefined ) { // 是的话就应有selector属性
this.selector = selector.selector;
this.context = selector.context;
}//对应后,$( $( '#div1' ) ) 就等于 $( '#div1' ) 了
【191】return jQuery.makeArray( selector, this ); 源码笔记:
// 处理传数组、json,如$([]) $({})
return jQuery.makeArray( selector, this );
},
【191】return jQuery.makeArray( selector, this ); 备注:
// $.makeArray( )会把类数组转成真正的数组
// aDiv为一个节点集合,节点数为3,像数组,但却不能用数组方法
$.makeArray( aDiv ).push( )// 已转成数组,这下可用数组方法了
// $.makeArray( )传二参时,可转json
$.makeArray( aDiv, { length : 0 } );
//{ 0 :'div', 1 :'div', 2 :'div', length : 3 }
网友评论