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);
}
相關文章
相關標籤/搜索