angular 之 jqLite

背景css

节点类型html

var NODE_TYPE_ELEMENT = 1;   // element
var NODE_TYPE_ATTRIBUTE = 2;  // attribute
var NODE_TYPE_TEXT = 3;   // text
var NODE_TYPE_COMMENT = 8;   // comment
var NODE_TYPE_DOCUMENT = 9;   // document 
var NODE_TYPE_DOCUMENT_FRAGMENT = 11;   // document fragment

对于 jqLite主要实现如下方法node

addClass

实现原理:主要是判断 setAttribute是否存在,借助 setAttribute 和getAttribute 方法实现jquery

具体实现:主要是借助 getAttribute 查找该元素原始的css 内容,而后查找这个css 内容中是否拥有新的class,若是没有就添加进去,而后把更新以后的css 内容 使用setAttribute 更新css 内容。缓存

function jqLiteAddClass(element,cssClasses){
    if(element && element.setAttribute){
        // 获取原来的css
        var exisingClass = ('' + (element.getAttribute('class') || '') + '').replace(/[\n\t]/g.' ');
        
        forEach(classClasses.split(' '),function(cssClass){
           cssClass = trim(cssClass);
           // 若是存在的class 中不存在你须要添加的对象 
           if(existingClasses.indexOf('' + cssClass + '') === -1){
               // 添加进去 
               existingClasses += cssClass + ' ';
           } 
        })
        // 更新元素的css 结果
        element.setAttribute('class',trim(exisingClass ));
    }
}


after

实现原理:主要是借助 parentNode 和 insertBefore 实现app

具体实现:主要是查找到 element.nextSibling 将 newElement 插入到 nextSibling以前。dom

after:function(element,newElement){
    var index = element,parent = element.parentNode;
    newElement = new JQLite(newElement);
    
    for(var i = 0,ii = newElement.length;i<ii;i++){
        var node = newElement[i];
        // 主要借助于 insertBefore 方法 
        parent.insertBefore(node,index.NextSibling);
        index = node;
    }
}


append

实现原理:主要是先利用nodeType 节点的类型,只有符合条件的节点类型才能被append ,而后利用appendChild方法实现append 功能
函数

具体实现:获取节点类型(nodeType),若是不知足条件的节点类型则不作处理,不然就将新要插入的节点插入到节点中去(appendChildoop

append:function(element,node){
    var nodeType  = element.nodeType;
    if(nodeType !== 1 && nodeType !== 11){
        return;
    }
    
    node = new JQLite(node);
    
    for(var i = 0,ii = node.length;i<ii;i++){
        var child = node[i];
        // 主要经过appendChild 方法实现 
        element.appendChild(child);
    }
}


attr

实现原理:setAttribute,getAttribute,removeAttributeui

主要实现:先获取节点类型,若是节点类型不知足条件,则直接返回,若是知足则再判断名称是不是boolean 类型(multiple,selected,checked,disabled,readyOnly,required,open),则赋值true 或者 false。再者去判断是否存在value 若是存在就调用setAttribute 方法设置属性,若是不存在,则调用getAttribute 方法获取属性。

var BOOLEAN_ATTR = {};

forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),function(value){
    BOOLEAN_ATTR[lowercase(value)] = value;
})


attr:function(element,key,value){
    var nodeType = element.nodeType;
    if(nodeType === 3 || element === 2 || element === 8){
        return;
    }
    var lowercasedName = lowercase(name);
    // 是否知足boolean 类型 的参数 
    if(BOOLEAN_ATTR[lowercasedName]){
        if(isDefined(value)){
            if(!!value){
                element[name] = true;
                element.setAttribute(name,lowercasedName);
            } 
            else{
                element[name] = false;
                element.removeAttribute(name);
            }   
        }
        else{
        
            // element.attribute.getNamedItem(name)  是 xml dom 的方法 
            return (element[name] || (element.attribute.getNamedItem(name) || noop).specified) ? lowercasedName: undefined;
        }
    }
    // value 是否存在 
    else if(isDedined(value)){
        element.setAttribute(name,value);
    }
    //  查看是否存在getAttribute 方法 
    else if(element.getAttribute){
        // the extra argument '2' is to get the right thing for a.href in ie,see jquery code 
        // some element (eg:Document) don't have get attribute, so return undefined;    
        var ret = element.getAttribute(name,2);
        return ret === null ? undefined : ret;
    }
    
}


bind

比较复杂 待定

children

实现原理: childNodes 

主要实现:主要遍历element 对象的 childNodes,而后判断 子节点类型是不是 NODE_TYPE_ELEMENT类型,若是是就返回

children:function(element){
    var children = [];
    forEach(element.childNodes,function(ele){
        // 符合条件的 节点类型 
        if(ele.nodeType === 2){
            children.push(ele);
        }
    })
    return children;
}

clone

实现原理:cloneNode

主要实现:主要利用cloneNode 方法实现的

function jqLiteClone(element){
    return element.cloneNode(true);
}

contents

实现原理:contentDocument  childNodes

主要实现:首先获取元素的contentDocument 对象,若是获取不到就获取他的childNodes 再获取不到 返回 [ ]

content:function(element){
    return element.contentDocument || element.childNodes || [];    
}

css

实现原理: element.style   

主要实现:主要根据 element.style 而后继续获取所须要的name ,也能够给name 赋值。

css:function(element,name,value){
    name = camelCase(name);
    // 若是定义了value 的值 
    if(isDefined(value)){
        element.style[name] = value;    
    }
    else{
        return element.style[name];    
    }
}


data


detach



empty


eq

实现原理: this[index]

主要实现: 若是 index 是正数的话,则取其中的第N个元素,不然取 this.length + index 个元素 

eq:function(index){
    return index >=0 ? jqLite(this[index]) : jqLite(this[this.length + index]);
}


find

实现原理:getElementByTagName

主要实现:主要根据getElementByTagName实现

find:function(element,selector){
    if(element.getElementByTagName){
        return element.getElementByTagName(selector);
    }
    else {
        return [];
    }
}

hasClass

实现原理:getAttribute

主要实现:先判断要选择的元素是否拥有getAttribute方法,而后利用 getAttribute 搜索出class 实现

function jqLiteHasClass(element,selector){
    if(!element.getAttribute){
        return false;
    }
    var exitClasses =  ' ' + (element.getAttribute('class') || ' ') + ' ';
    exitClasses = exitClasses.replace(/\n\t/g,' ');
    return exitClasses.indexOf(' ' + selector + ' ') > -1;
    
}

html

实现原理:innerHTML 

主要实现:若是是获取某个元素的html  利用的是 innerHTML属性,若是是给某个属性赋值的话,

html:function(element,value){
    // 若是 value 为空的话,则表示须要获取element 对象的 html 值,也就是innerHTML的内容
    if(isUndefined(value)){
        return element.innerHTML;
    }
    
    // 若是value 存在的话,则表示赋值操做
}


hasClass

实现原理: getAttribute('class')  ,  indexOf()

主要实现: 主要经过 getAttribute('class') 获取到全部的 class 内容,而后经过indexOf 查看class 是否存在里面

function hasClass(element,selector){
    if(!element.getAttribute) return false;
    
    return  (element.getAtribute('class')).replace(/[\n\t]/g, '' ).indexOf( selector ) > -1;
    
}


next

实现原理:nextElementSibling

主要实现:直接返回对象的 nextElementSibling

next:function(element){
    return element.nextElementSibling;
}


on


off


one


parent

实现原理:parentNode, nodeType 

主要实现:获取element 的 parentNode 对象 ,而后判断parent 对象类型是否合法,合法就返回,不合法就返回null

parent:function(element){
    var parent = element.parentNode;
    return parent && parent.nodeType !== 11 ? parent : null;
}


prepend

实现原理: nodeType  fristChild  insertBefore

主要实现:先判断类型,若是符合类型,则先获取元素的firstChild,而后遍历须要插入的节点,调用insertBefore插入进去就能够了

prepend:function(element,node){
    if(element.nodeType === 1){
        var index = element.firstChild;
        
        forEach(new JQLite(node),function(child){
           element.insertBefore(child,index); 
        });
    }
}


prop

实现原理:非常霸气的直接取对象的属性

主要实现:

prop:function(element,name,value){
     if(isDefined(value)){
         element[name] = value;
     }
     else {
         return element[name];
     }       
}

ready

实现原理: DOMContentLoaded, load  ,document.readyState 

主要实现:

ready:function(fn){
    var fired = false;
    
    function trigger(){
        if(fired) return;
        tired = true;
        fn();
    }
    
    if(document.readyState === 'complete'){
        setTimeout(trigger,1);
    }
    else{
        this.on('DOMContentLoaded',trigger);
        
        JQLite(window).on('load',trigger);
    }
}


remove

实现原理:parentNode,removeChild

主要实现:

function jqLiteRemove(element,keepData){
    if(!keepData){
        // 待定。。。
    }
    var parent = element.parentNode;
    if(parent){
        parent.removeChild(element);
    }
    
}


removeAttr

实现原理: removeAttribute

具体实现:

removeAttr:function(element,name){
    element.removeAttribute(name);    
}


removeClass

实现原理: setAttribute ,getAttribute('class'), replace(cssClass',' ')

具体实现: 主要利用getAttribute 获取class 内容,而后利用replace替换掉须要移除的属性 .

function jqLiteRemoveClass(element,cssClasses){
    if(cssClasses && element.setAttribute){
        forEach(classClasses.split(' '),function(cssClass){
            element.setAttribute('class',trim(
                ('' + (element.getAttribute('class')) + '')
                // 移除无效符号
                .replace(/[\n\t]/g, ' ')
                // 移除 须要移除的属性
                .replace('' + trim(cssClass) + '', '');            
            ))        
        })
    }
}


removeData



replaceWith

实现原理:

具体实现:仍是须要经过查找到须要替换元素的parentNode 节点,而后利用 replaceChild实现

replaceWith:function(element,replaceNode){
    var index,parent = element.parentNode;
    // 移除element 绑定的数据
    forEach(new JQLite(replaceNode),function(node){
        if(index){
            parent.insertBefore(node,index.nextSibling);
        }
        else{
            parent.replaceChild(node,element);
        }
        index = node;
    })    
}


text

实现原理:textContent

具体实现:

text: (function(){
    getText.$dv = '';
    return getText;
    
    function getText(element,value){
        if(isUndefined(value)){
            var nodeType = element.nodeType;
            // 必须知足条件才行。
            return (nodeType === 1|| nodeType === 3) ? element.textContent :'';
        }
        element.textContent = value;    
    }
})()


toggleClass

实现原理: 

主要实现:首先判断是否存在第三个参数,若是存在的话,则根据参数是否为true 则调用addClass 不然调用 removeClass,若是不存在的话,则调用hasClass函数,是否存在这个class ,根据是否存在设置第三个参数。

toggleClass:function(element,selector,condition){
    if(selector){
        forEach(selector.split(' '),function(className){
            var classCondition = condition;
            if(isUndefined(classCondition)){
                classCondition = !hasClass(element,className);
            }
            (classCondition) ? addClass(element,className) : removeClass(element,className);            
        })
    }
}


triggerHandler



unBind



val

实现原理: value , text  , nodeName

主要实现: 主要区分select 对象, 由于能够multiple 多选,因此须要判断nodeName 是不是 select 

val:function(element,value){
    if(isUndefined(value)){
        if(element.multiple && nodeName_(element) === 'select'){
            var result = [];
                forEach(element.options,function(option){
                    if(option.selected){
                        result.push(option.value || option.text);
                    }
                });            
            return result.length === 0 ? null: result;
        }
        return element.value;
    }
    // 不然就是赋值操做
    element.value = value;
}


wrap

实现原理: 

主要实现: 找到element 元的父亲,将自身缓存下,而后将wrapNode替换掉本来直接所在的element 对方,而后将element 插入到wrapNode中去。

wrap:function(element,wrapNode){
    // 克隆一个对象
    wrapNode = jqLite(wrapNode).eq(0).clone()[0];
    // 获取父亲
    var parent = element.parentNode;
    
    if(parent){
            // 若是存在父亲,就将element替换成wrapNode 对象
            parent.replaceChild(wrapNode,element);
    }
    // wrapNode节点插入 child 节点。
    wrapNode.appendChild(element);
}
相关文章
相关标签/搜索