淘宝Kissy框架分析【七】

今天开始就正式进入了DOM文件夹部分. DOMAPI算是比较难搞的部分.KISSY也在不断完善中.所以现在实现的不是很全面.这篇我们主要看下

dom.js和dom-class.js

dom.js只定义了个命名空间.代码还没有具体实现

J1616.add( ' dom ' function (J) {
    J.DOM  =  {
        _isElementNode:  function (elem) {
            
return  elem  &&  elem.nodeType  ===   1 ;
        }
    };
});

 

但由于DOM方法都是扩展在J.DOM命名空间下.所以这个文件是必须的.

dom-class.js是对元素的class进行了控制.

【程序源码】

J1616.add( ' dom-class ' function (J, undefined) {
    
var  SPACE  =   '   ' ,
        DOM  =  J.DOM,
        REG_SPLIT  =   / [\.\s]\s*\.? / ,
        REG_CLASS  =   / [\n\t] / g;

    J.mix(DOM, {
        
//  selector是否存在指定的class
        hasClass:  function (selector, value) {
            
return  batch(selector, value,  function (elem, classNames, cl) {
                
var  elemClass  =  elem.className;
                
if  (elemClass) {
                    
var  className  =  SPACE  +  elemClass  +  SPACE, j  =   0 , ret  =   true ;
                    
for  (; j  <  cl;  ++ j) {
                        
if  (className.indexOf(SPACE  +  classNames[j]  +  SPACE)  <   0 ) {
                            ret  =   false ;
                            
break ;
                        } 
                    }
                    
if  (ret)  return   true
                } 
            },  true );
        },
        
//  为selector 添加class
        addClass:  function (selector, value) {
            batch(selector, value,  function (elem, classNames, cl) {
                
var  elemClass  =  elem.className;
                
if  ( ! elemClass) {
                    elem.className  =  value;
                } 
                
else  {
                    
var  className  =  SPACE  +  elemClass  +  SPACE, setClass  =  elemClass, j  =   0 ;
                    
for  (; j  <  cl;  ++ j) {
                        
if  (className.indexOf(SPACE  +  classNames[j]  +  SPACE)  <   0 ) {
                            setClass  +=  SPACE  +  classNames[j];
                        }
                    }
                    elem.className  =  J.trim(setClass);
                }
            });
        },
        
//  为指定的selector删除class
        removeClass:  function (selector, value) {
            batch(selector, value,  function (elem, classNames, cl) {
                
var  elemClass  =  elem.className;
                
if  (elemClass) {
                    
if  ( ! cl) {
                        elem.className  =   '' ;
                    } 
                    
else  {
                        
var  className  =  (SPACE  +  elemClass  +  SPACE).replace(REG_CLASS, SPACE), j  =   0 ;
                        
for  (; j  <  cl; j ++ ) {
                            className  =  className.replace(SPACE  +  classNames[j]  +  SPACE, SPACE);
                        }
                        elem.className  =  J.trim(className);
                    }
                } 
            });
        },
        
//  用新class替换旧的class
        replaceClass:  function (selector, oldClassName, newClassName) {
            DOM.removeClass(selector, oldClassName);
            DOM.addClass(selector, newClassName);
        },
        
//  切换指定的class. state是强制删除或者添加
        toggleClass:  function (selector, value, state) {
            
var  isBool  =  J.isBoolean(state), has;

            batch(selector, value,  function (elem, classNames, cl) {
                
var  j  =   0 , className;
                
for  (; j  <  cl;  ++ j) {
                    className  =  classNames[j];
                    has  =  isBool  ?   ! state : DOM.hasClass(elem, className);
                    DOM[has  ?   ' removeClass '  :  ' addClass ' ](elem, className);
                }
            });
        }
    });

    
function  batch(selector, value, fn, resultIsBool) {
        
if  ( ! (value  =  J.trim(value)))  return  resultIsBool  ?   false  : undefined;
        
        
var  elems  =  J.query(selector),
            i  =   0 , len  =  elems.length,
            classNames  =  value.split(REG_SPLIT),
            elem, ret;
        
for  (; i  <  len;  ++ i) {
            elem  =  elems[i];
            
if  (elem.nodeType  ===   1 ) {
                ret  =  fn(elem, classNames, classNames.length);
                
if  (ret  !==  undefined)  return  ret; 
            } 
        }
        
if  (resultIsBool)  return   false
    }
});

1. batch方法

这个方法是批量元素处理的核心方法.总共4个参数:

1) selector[选择器] 这个会通过J.query通过选择器选择出所有符合条件的元素. J.query会在下节讲解.

2) value要进行操作的样式名称.支持(acls bclas) (acls.bcls) (acls    .bcls)等宽松模式.

3) fn 回调函数 选择器选出的NodeList  value传入的classNames, classNames的长度会循环并作为参数传入回调函数.

4) resultIsBool 如果为true那么返回值为true或false, 否则为undefined.

 

2.addClass方法.

作用: 为selector筛选出的元素都追加value指定的class 

我们下面测试的所有HTML都需要引入这些文件

< style type = " text/css " >
.red {color:red}
.blue {background - color: blue}
< / style>
< script src = " ../j1616/j1616.js " >< / script>
< script src = " ../j1616/j1616-ua.js " >< / script>
< script src = " ../j1616/j1616-lang.js " >< / script>
< script src = " dom.js " >< / script>
< script src = " dom-class.js " >< / script>
< script src = " selector.js " >< / script>
< / head>
< body >
< div id = " odiv " > div < / div>
< div id = " odiv2 " > div2 < / div>

测试用例

J.DOM.addClass( ' #odiv2, #odiv ' ' red blue ' );

这样我们就为id为odiv2, odiv的元素都追加了red和blue的class ==> 字体变红,背景色变蓝.  

3.hasClass方法

作用:判断选择器筛选出的元素是否含有value指定的class. 只要有一个元素符合那么就为true. 如果所有的元素都不匹配value那么就为false.

测试用例

J.DOM.addClass( ' #odiv2 ' ' red blue ' );  //  事先为odiv2 添加red和blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  只有odiv2符合 那么就返回true

 

4.removeClass方法

作用:为选择器筛选的元素删除value给定的class.

测试用例

J.DOM.addClass( ' #odiv2 ' ' red blue ' );  //  事先为odiv2 添加red和blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  只有odiv2符合 那么就返回true
J.DOM.removeClass( ' #odiv2 ' ' blue ' );  //  删除了blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  此时blue样式已被删除 所以返回false

 

5.replaceClass方法

作用:用一个新的class替换一个class

测试用例

J.DOM.addClass( ' #odiv2 ' ' red blue ' );  //  事先为odiv2 添加red和blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  只有odiv2符合 那么就返回true
J.DOM.removeClass( ' #odiv2 ' ' blue ' );  //  删除了blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  此时blue样式已被删除 所以返回false
J.DOM.replaceClass( ' #odiv2 ' ' red ' ' blue ' );  //  div元素的背景色变蓝 因为用blue替换了red

 

6.toggleClass方法

作用:切换一个指定的class. 如果第一次样式存在 那么就删除 第二次就又追加上 以此类推.

测试用例:

J.DOM.addClass( ' #odiv2 ' ' red blue ' );  //  事先为odiv2 添加red和blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  只有odiv2符合 那么就返回true
J.DOM.removeClass( ' #odiv2 ' ' blue ' );  //  删除了blue样式
J.log(J.DOM.hasClass( ' #odiv, #odiv2 ' ' red blue ' ));  //  此时blue样式已被删除 所以返回false
J.DOM.replaceClass( ' #odiv2 ' ' red ' ' blue ' );  //  div元素的背景色变蓝 因为用blue替换了red
J.DOM.toggleClass( ' #odiv2 ' ' blue ' );  //  刚才blue样式存在,那么这次就将其移除
J.DOM.toggleClass( ' #odiv2 ' ' blue ' );  //  刚才blue样式被移除了.那么这次就添加上

 

这个方法还支持第三个参数state.这个参数可以强制指定是删除还是添加样式.如果true添加,如果false删除 

J.DOM.toggleClass( ' #odiv2 ' ' blue ' false );  //  这样就强制要删除blue样式

 

【总结】

整个实现没有什么难度.流程就是. 通过batch去获得selector的所有元素.和所有的样式classNames.然后循环所有元素,依次将元素和所有样式数组传入回调方法中去执行addClass.removeClass等一系列处理后.然后返回. batch再返回这些返回值就可以了.

 

下节我们将要讲解选择器selector.js 

转载于:https://www.cnblogs.com/bluedream2009/archive/2010/06/20/1761469.html

你可能感兴趣的:(淘宝Kissy框架分析【七】)