jQuery.fn.init
主要功能分支:
- selector可以转换为false,如””,null,undefined,false,返回this 示例:
$(undefined)
- selector为字符串 示例:
$("<div></div>)或$("#id")或$("div")
等 - selector为DOM元素,手动设置第一个元素和属性context指向该DOM元素,属性length为1,然后返回包含该DOM元素引用的jQuery对象 示例:
$(document)
- selector是函数,则认为是绑定ready事件,示例:
$(function(){})
- selector是jQuery对象,参数selector包含属性selector,则认为它是jQuery对象,将会复制它的属性selector和context 示例:
$($('div p'))
jQuery选择器支持9种方式的处理
API:
- jQuery( selector[,context] ); $(“.test”,$(“body”));
- jQuery( element ) 示例:$(document);
- jQuery( elementArray ) 示例:$(myForm.elements);
- jQuery( object ) 示例:$({foo:”bar”,hello:”hello”});
- jQuery( jQuery object ) 示例:$($(‘.test’));
- jQuery(); 示例:$();$(false);
- jQuery( html[,ownerDocument] ) 示例:$(“\
“,document); - jQuery( html,attributes ) 示例:$(“\“,{“src”:”a.png”});
- jQuery( callback ) 示例:$(function(){});
代码组织结构:1
init : function(selector, context, rootjQuery){
var match,elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if(!selector){
return this;
}
// Handle HTML strings
if(typeof selector === 'string'){
// HANDLE: $(DOMElement)
}else if(selector.nodeType){
this.context = this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
}else if(jQuery.isFunction(selector)){
return rootjQuery.ready(selector);
}
if(selector.selector !== undefined){
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray(selector,this);
}
正则解析
rquickExpr1
var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
(?:pattern)
:匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“or”字符 (|) 组合模式部件的情况很有用。例如,’industr(?:y|ies) 是比 ‘industry|industries’ 更经济的表达式。- 选择二义 : 匹配
\s*(<[\w\W]+>)[^>]*
开头或#([\w-]*)
结尾 - \s*(<[\w\W]+>)[^>]*:
- \s*:匹配任何空白字符,包括空格、制表符、换页符等等零次或多次,等价于{0,}
- (pattern):匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,使用 $0…$9 属性
- [\w\W]+:匹配于’[A-Za-z0-9]’或[^A-Za-z0-9]’ 一次或多次,等价{1,}
- (<[wW]+>) :这个表示字符串里要包含用\<>包含的字符,例如\
,\
等等都是符合要求的 - [^>]* : 负值字符集合,字符串尾部是除了>的任意字符或者没有字符,零次或多次等价于{0,}
- #([\w-]*):匹配结尾带上#号的任意字符,包括下划线与-
- exec方法介绍:如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。
- 此数组的第 0 个元素是与正则表达式相匹配的文本
- 第1个元素是与RegExpObject的第1个子表达式相匹配的文本(如果有的话)
- 第2个元素是与RegExpObject的第2个子表达式相匹配的文本(如果有的话),以此类推
- 此数组的第 0 个元素是与正则表达式相匹配的文本
正则测试:1
2
3
4
5
6var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
console.log(rquickExpr.exec("#id"));//["#id",undefined,"id"];
console.log(rquickExpr.exec("<div>"));//["<div>","<div>",undefined];
console.log(rquickExpr.exec(" <div>"));//[" <div>","<div>",undefined];
console.log(rquickExpr.exec(" <div>abc#id"));
console.log(rquickExpr.exec("#id<div>"));//null
rsingleTag1
var rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
- ^<(\w+)\s*\/?>:以
<
开头,跟一个或多个字符和任意个空白字符,接着判断/
出现0次或1次,从而判断是否自关闭或不关闭,(\w+)
该分组中不包含左右尖括号,不能包含属性。 - (?:<\/\1>|)$:
\1
指向匹配的第一个分组(\w+)
正则测试:1
2
3
4
5var rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
rsingleTag.exec("<div>");//["<div>", "div"]
rsingleTag.exec("<div>abc");//null
rsingleTag.exec("<img/>");//["<img/>", "img"]
rsingleTag.exec("<img name/>");//null
match的取值
1 | if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { |
selector如果以<
开头,以>
结尾,并且selector.length大于3就假设这个字符串是HTML片段。否则,用正则rquickExpr.exec检测较为复杂的HTML代码或#id。相关结果都存储在match中。
- match[0]:表示输入的selector
- match[1]:表示匹配的HTML代码或undefined
- match[2]:表示匹配的Id或undefined
匹配模式一:html代码\
参数selector是HTML代码,或者是#id,并且未传入参数context1
if( match && (match[1] || !context) ){}
参数selector是HTML代码的处理
1 | if(match[1]){ |
一. 当传入context时,判断context是否为jQuery对象,如果是直接取context[0],直接取context的html元素。1
context && context instanceof jQuery ? context[0] : context;
二. ownerDocument与documentElement区别1
context && context.nodeType ? context.ownerDocument || context : document
- node.ownerDocument是Node对象的属性,返回当前节点所在文档的文档节点,即document对象
- document.documentElement是Document对象属性,返回文档对象(document)的根元素(例如:HTML文档的元素)
三. 调用jQuery.merge()和jQuery.parseHTML(),进行创建新元素或创建代码片断的处理
- jQuery.merge(first,second)合并两个数组内容到第一个数组。
- jQuery.parseHTML(data[,context][,keepScripts])将字符串转换为一组DOM元素。
jQuery.parseHTML1
2var str = "Hello,<b>my name is</b> jQuery.";
$.parseHTML(str);//["Hello,",<b>my name is</b>," jQuery."]
jQuery.parseHTML的源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20parseHTML:function(data,context,keepScripts){
if(!data || typeof data !== "string"){
return null;
}
if(typeof context === "boolean"){
keepScripts = context;
context = false;
}
context = context || document;
var parsed = rsingleTag.exec(data),
scritps = !keepScripts || [];
if(parsed){
return [context.createElement(parsed[1])];
}
parsed = jQuery.buildFragment([data],context,scritps);
if(scritps){
jQuery(scritps).remove();
}
return jQuery.merge([],parsed.childNodes);
}
var parsed = rsingleTag.exec(data);
通过正则判断传入的data是否为单独标签,如果是则调用createElement创建标签对应的DOM元素,并且把创建的DOM元素放入数组中,是为了在后面方便的调用jQuery.merge()方法。parsed = jQuery.buildFragment([data],context,scripts);
如果data是个复杂的html代码,则利用浏览器的innerHTML机制创建DOM元素。
四. 当HTML代码是单独标签,且第二参数context为一个非空纯对象1
2
3
4
5
6
7
8
9if(rsingleTag.test(match[1]) && jQuery.isPlainObject(context)){
for(match in context){
if(jQuery.isFunction(this[match])){
this[match](context[match]);
}else{
this.attr(match,context[match]);
}
}
}
jQuery.isPlainObject()
判断当前传入的内容是否是纯粹对象(通过”{}”或new Object创建)
示例:1
2
3$("<div></div>");
$("<img/>");
$("<div></div>",{"test","test"});
通过for读取context属性,如果当前jQuery对象也有这个属性并且属性为function,则调用该jQuery对象的这个属性,传入的参数为context中该属性的值;如果该属性不为function,则调用attr,把context的当前属性和值添加到当前jQuery对象上。1
2
3var jqHTML = $("<div></div>",{class:'css-class',data-name:'data-val'});
jqHTML.attr['class'];//css-class
jqHTML.attr['data-nae'];//data-val
匹配模式二:$(“#id”),context未传入
参数selector是#id,context未传入时的处理
1 | if ( match && (match[1] || !context) ) { |
1 | elem = document.getElementById( match[2] ); |
一. 调用document.getElementById()查找含有指定id属性的DOM元素。1
elem = document.getElementById(match[2]);
二. 检查parentNode属性,因为Blackberry4.6会返回已经不在文档中的DOM节点1
elem && elem.parentNode
如果所找到的元素的id与传入的值不等,则调用Sizzle查找并返回一个含有选中元素的新jQuery对象。即使是document.getElementById()这样核心的方法也需要考虑浏览器的兼容问题,在IE6,IE7,某些版本的Opera中,可能会按属性name查找而不是id.
如下面的示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="description" content="head meta description">
</head>
<body>
<div id="description">
body div description
</div>
<form name="divId">
<div id="divId"></div>
</form>
<script></script>
</body>
</html>
三. 如果所找到的元素的属性id值与传入的值相等,则设置第一个元素,属性length,selector,context,并返回当前jQuery对象。1
2
3
4
5this.length = 1;
this[0] = elem;
this.context = document;
this.selector = selector;
匹配模式三:$(selector),selector选择器表达式
如果第一个元素是一个选择器,如.className
,且未指定上下文1
return rootjQuery.find(selector);
匹配模式四:$(selector,context)context是jQuery对象
如果第一个元素是一个选择器,如.className
,指定上下文是jQuery对象1
return context.find(selector);
两种模式结合统一这样处理:1
return (context || rootjQuery).find(selector);
匹配模式五:$(selector,context)context不是jQuery对象
如果第一个元素是一个选择器,如.className
,指定上下文是不是jQuery对象,则执行1
this.constructor(context).find(selector);
先创建一个包含了context的jQuery对象,然后在该jQuery对象上调用方法.find()
。
匹配模式六:$(jQuery对象)
如果参数selector含有属性selector,则认为它是jQuery对象,将会复制它的属性selector和context。1
2
3
4if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
匹配模式七:$(fn)
如果参数selector是函数,则认为是绑定ready事件。1
return rootjQuery.ready(selector);