通过给元素添加删除指定的样式类名用来修改样式的方法有 addClass 与 removeClass,为每个匹配的元素添加指定的样式类名,对元素的样式操作,底层的实现就是修改元素的className值,实现的功能:
增加一条样式规则: .addClass('myClass') 增加多条样式规则: .addClass('myClass yourClass')
传递回调遍历样式规则:
$("ul li:last").addClass(function(index) { return "item-" + index; });
从接口传参去分析这个实现手法,参考右边的代码addClass我把代码简略的分了几个步骤:
/\S+/g
空白分组这里就不详讲,看看代码就能理解重点说一下传递回调函数的设计,官方给的测试案例:
<p class ='selected highlight'>Goodbye</p> <p class ='selected1 highlight1'>Goodbye</p> <p class ='selected2 highlight2'>Goodbye</p>
增加样式代码:
$(p).addClass(function(index,className){ index className 0 "selected highlight" 1 "selected1 highlight1" 2 "selected2 highlight2" });
遍历出所有的 P 节点,并找其对应的 class,返回给每一个回调函数,看看源码的设计:
//如果传递的是回调函数,递归调用 ⑴ if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { //each addClass回调 jQuery( this ).addClass( value.call( this, j, this.className ) ); }); }
不管是写插件还是其他的,只要是设计操作 DOM 的,在 jQuery 内部就的到 this.each 方法,原因很简单jQuery就是一个数组保存着所有对应的节点的下标。
内部在传递一个编写好的回调函数,传递给 each 方法 ,each 方法理解就是一个循环方法,分解出 jQuery 数组中每一个下标元,然后把每一个元素返回给外部回调。
这里再进一步替换下代码就很明显了:
function( i, obj[ i ] ) { jQuery( this ).addClass( value.call( this, j, this.className ) ) }
这里的 this 是指向的每一个 p 元素节点,因为 callback.call 了一下,把每一个上下文指定到当前的函数了,所以 this 就是对应的 obj[i],最后执行的代码就是:
value.call( this, j, this.className )
value 就是最外层用户定义的回调了,复制代码:
$(p).addClass(function(index,className){ // index className // 0 "selected highlight" // 1 "selected1 highlight1" // 2 "selected2 highlight2" });
这里意外的发现 jQuery Api没给出还包装了一层 jQuery( this ).addClass ,那么意味着 jQuery 还可以接受用户最外层的返回参数,然后再调用 addClass 给当前节点增加新的类名:
jQuery( this ).addClass( value.call( this, j, this.className ) ); p.addClass(function(index,className){ return 'aaaa' });
<!doctype html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <style> .test { margin: 4px; font-size:16px; font-weight:bolder; } .blue { color:blue; } .under { text-decoration:underline; } .highlight { background:yellow; } </style> <script src="http://code.jquery.com/jquery-latest.js"></script> <title></title> </head> <body> <p class="under">慕课网</p> <button id="addClass">模拟jQuery的addClass("blue highlight under")方法</button> <button id="removeClass">模拟jQuery的removeClass("blue highlight under")方法</button> <script type="text/javascript"> var p = $("p")[0]; /////////// //增加多个样式 // /////////// $("#addClass").click(function(){ addClass(p, "blue highlight under") }) $("#removeClass").click(function(){ removeClass(p, "blue highlight under") }) ///////// //增加样式 // ///////// function addClass(elem,value) { var classes, cur, clazz, j, finalValue // 如果参数是多个样式设置"blue highlight under"按照\/S+\g空格分割 classes = (value || "").match(/\S+/g) || []; //如果是元素节点,并且有class属性 //拼接成 " blue highlight under "形式,加上前后空格 cur = elem.nodeType === 1 && (elem.className ? (" " + elem.className + " ").replace(/[\t\r\n\f]/g, " ") : " " ); //如果存在样式 if (cur) { j = 0; while ((clazz = classes[j++])) { //查找下是否不是有重复的,没有就叠加 if (cur.indexOf(" " + clazz + " ") < 0) { cur += clazz + " "; } } // 去掉前后的空格 finalValue = jQuery.trim(cur); if (elem.className !== finalValue) { //赋值 elem.className = finalValue; } } } ///////// //移除样式 // ///////// function removeClass(elem, value) { var classes, cur, clazz, j, finalValue // 如果参数是多个样式设置"blue highlight under"按照\/S+\g空格分割 classes = (value || "").match(/\S+/g) || []; //如果是元素节点,并且有class属性 //拼接成 " blue highlight under "形式,加上前后空格 cur = elem.nodeType === 1 && (elem.className ? (" " + elem.className + " ").replace(/[\t\r\n\f]/g, " ") : " " ); //如果存在样式 if (cur) { j = 0; while ((clazz = classes[j++])) { //与addClass的区别在这里 while (cur.indexOf(" " + clazz + " ") >= 0) { cur = cur.replace(" " + clazz + " ", " "); } } // 去掉前后的空格 finalValue = jQuery.trim(cur); if (elem.className !== finalValue) { //赋值 elem.className = finalValue; } } } </script> </body> </html>