john's tech blog

hope is coming


  • 首页

  • 标签

  • 归档

jquery_sibling

发表于 2016-09-06 | 更新于 2019-05-09

jquery1.0源码解读

jquery 实例方法siblings 定义在jQuery.macros对象中,通过jQuery.each定义:

1
2
3
4
5
6
7
8
jQuery.each( jQuery.macros.axis, function(i,n){
jQuery.fn[ i ] = function(a) {
var ret = jQuery.map(this,n);
if ( a && a.constructor == String )
ret = jQuery.filter(a,ret).r;
return this.pushStack( ret, arguments );
};
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
axis: {

parent: "a.parentNode",

ancestors: jQuery.parents,

parents: jQuery.parents,

next: "jQuery.sibling(a).next",

prev: "jQuery.sibling(a).prev",

siblings: jQuery.sibling,

children: "a.childNodes"
}

我们看到siblings实际是调用jQuery静态方法sibling:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 sibling: function(elem, pos, not) {
var elems = [];

var siblings = elem.parentNode.childNodes;
for ( var i = 0; i < siblings.length; i++ ) {
if ( not === true && siblings[i] == elem ) continue;

if ( siblings[i].nodeType == 1 )//表明是元素
elems.push( siblings[i] );
if ( siblings[i] == elem )
elems.n = elems.length - 1;
}

return jQuery.extend( elems, {
last: elems.n == elems.length - 1,
//0%2等于0
cur: pos == "even" && elems.n % 2 == 0 || pos == "odd" && elems.n % 2 || elems[pos] == elem,
prev: elems[elems.n - 1],
next: elems[elems.n + 1]
});
}

用法例如:
$('li.third-item').siblings().css('background-color', 'red');

jquery_clean源码分析

发表于 2016-09-05 | 更新于 2019-05-07

jquery1.0源码解读

jQuery函数

1
2
3
4
5
6
7
8
// Handle HTML strings
//处理html字符串
//以非<开头 当中<> 非>结束
//如果a是html代码,$("<div/>"),把html代码转成Dom元素
//jQuery.clean 就是把html代码 转换成Dom元素数组
var m = /^[^<]*(<.+>)[^>]*$/.exec(a);
if ( m ) a = jQuery.clean( [ m[1] ] );
...省略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
   //比如$('<div>123</div>,<a><223/a>')
//用调用jQuery.clean方法返回
//a 需是一个数组
clean: function(a) {
var r = [];
for ( var i = 0; i < a.length; i++ ) {
if ( a[i].constructor == String ) {

var table = "";
//indexOf 返回0 !0才是正确的
if ( !a[i].indexOf("<thead") || !a[i].indexOf("<tbody") ) {
table = "thead";
a[i] = "<table>" + a[i] + "</table>";
} else if ( !a[i].indexOf("<tr") ) {
table = "tr";
a[i] = "<table>" + a[i] + "</table>";
} else if ( !a[i].indexOf("<td") || !a[i].indexOf("<th") ) {
table = "td";
a[i] = "<table><tbody><tr>" + a[i] + "</tr></tbody></table>";
}

var div = document.createElement("div");
div.innerHTML = a[i];//构造div 把table放在div中。

if ( table ) {
div = div.firstChild;// table元素

//如果table是 tr 那么 div就变成tr元素
//如果table是 td 那么 div也变成tr元素 ,但是下面的div就变成tr了。
if ( table != "thead" ) div = div.firstChild;//t的时候
if ( table == "td" ) div = div.firstChild;
}

for ( var j = 0; j < div.childNodes.length; j++ )
r.push( div.childNodes[j] );
} else if ( a[i].jquery || a[i].length && !a[i].nodeType )
for ( var k = 0; k < a[i].length; k++ )
r.push( a[i][k] );
else if ( a[i] !== null )
r.push( a[i].nodeType ? a[i] : document.createTextNode(a[i].toString()) );
}
return r;
}

jQuery.clean()方法源码分析(一)
[原创] jQuery源码分析-13 CSS操作-CSS-样式表-jQuery.fn.css()

jquery_pushstack函数分析

发表于 2016-09-04 | 更新于 2019-05-07

jquery1.0源码解读

pushStack函数

pushStack是个对象函数,不是静态方法,用jQuery.pushStack调用会报错,我们来看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//实例方法保证a是数组。。。
pushStack: function(a,args) {
//获取args中的最后一个参数
var fn = args && args[args.length-1];

if ( !fn || fn.constructor != Function ) {
内部维护一个stack数组。用来pop 或者push
if ( !this.stack ) this.stack = [];
this.stack.push( this.get() );//get()把当前对象压入堆栈
//jQuery.map( this, function(a){ return a } ) :
this.get( a );
} else {
var old = this.get();//里面调用map function ,返回当前jquery对象
this.get( a );//貌似是为了执行fn
if ( fn.constructor == Function )
return this.each( fn );
this.get( old );//重新返回old元素数组
}

return this;
}

我们看他关联的end函数:

1
2
3
end: function() {
return this.get( this.stack.pop() );//stack 保存了元素数组,get把当前元素数组 push 到新数组,1.0还没有prevObject
}

jquery的filter和grep函数思考

发表于 2016-09-03 | 更新于 2019-05-09

jquery1.0源码解读

filter函数首先根据参数not确定是不是筛选出不满足参数t的:
1.not为true时筛选出不满足参数t的元素:
构造function(a,f) {return jQuery.grep(a,f,true);},因为要传递true,所以只能构造。

2.not为false时筛选出满足参数t的元素:调用jQuery.grep

然后根据while ( t && /^[a-z[({<*:.#]/i.test(t) )来循环筛选元素

1.必须满足/^[a-z[({<*:.#]/i正则才会进入while循环,否则直接返回return { r: r, t: t };

2.进入循环后就开始应用jQuery.parse数组循环筛选:

因为jQuery.parse数组中包含S,Q两个正则常量:
1.//Look for a string-like sequence
replace( ‘S’, “([a-z-][a-z0-9-])” )
就是要找类似字符串的
2.//Look for something (optionally) enclosed with quotes
.replace( ‘Q’, “ ‘?\”?([^’\”]?)’?\”? *” ), “i” );
寻找通过引号关闭的
如果满足parse数组中的某个,那么就跳出for循环,这时候t = t.replace( re, "" ),t就把满足正则的替换为空了(ps:一般到这t就为空了。)
3.如果匹配出的结果中包含not,那么就递归进入filter继续筛选出not的元素。
4.如果没有not,那么就根据jQuery.expr找出符合筛选规则的函数进行eval
因为要传入字符串,所以用eval

1
2
3
eval("f = function(a,i){" +
( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +
"return " + f + "}");

最后通过grep函数传入f规则函数 再筛选出剩余的元素。

jquery_filter函数深入分析

发表于 2016-09-02 | 更新于 2019-05-07

jquery1.0源码解读

昨天分析each函数时发现最后调用了jQuery.filter(‘.example’,r)函数,我们再深入filter函数看看:

1
2
var g = not !== false ? jQuery.grep :
function(a,f) {return jQuery.grep(a,f,true);};

not参数为空,所以g为jQuery.grep。

t为.example,所以满足以下正则:

1
t && /^[a-z[({<*:.#]/i.test(t)

进入while循环,调用jQuery.parse解析数组,满足第四个正则元素([:.#]*)S,最后m为
0: “.example”
1: “.”
2: “example”
再进入jQuery.expr,因为m[1]为.,所以获得的expr为jQuery.className.has(a,m[2])
所以其实到最后就是再调用jQuery.grep函数通过jQuery.className.has筛选元素.

1…404142…47

John

232 日志
43 标签
GitHub Twitter
欢迎关注我的公众号:沉迷Spring
© 2023 johnwonder
由 Hexo 强力驱动 v3.2.0
|
主题 – NexT.Pisces v7.1.1
|
0%