DOM-10 【一篇文章搞懂DOM兼容性封装代码-常见练习代码】

封装工具

childNodes封装

封装理由:

  因为childNodes获取时会把子元素获取到,也就是会把文本节点、注释节点等获取到不便使用,所以封装。

封装思路:

  创建类数组以便于讲元素节点放入,通过获得节点长度循环,将nodeType===1的节点放入类数组

封装代码:

function elemChildren(node){
    var temp={
        'length':0,
        'push':Array.prototype.push,
        'splice':Array.prototype.splice
    },
    len = node.childNodes.length;
    for(var i =0;i<len;i++){
        var childItem=node.childNodes[i];
        if(childItem.nodeType===1){
            //temp[temp['length']]=childItem;
            //temp['length']++;
            temp.push(childItem);
        }
    }
    return temp;
}

parentNode封装

封装理由:

  因为普通的parentNode只能获取一层父元素,无法指定获取的父元素

封装思路:

  函数中传入tier层级参数,通过typeof判断非空,之后while循环 将tier累减不断重新赋值第一个参数

封装代码:

function parentNode(elem,tier){
    var type=typeof(tier);
    if(type==='undefined'){
        return elem.parentNode;
    }else{
        while(tier){
           elem= elem.parentNode;
           tier--;
        }
    }
    return elem;
}

insertAfter封装

封装理由:

  因为在Element中只有insertBefore,没有insertAfter方法

封装思路:

  判断兄弟元素是否存在,如果存在兄弟节点,则通过nextElementSibling来获得弟元素,在弟元素上insertBefore,如果没有弟元素则在当前元素的父元素上appendChild

封装代码:

Element.prototype.insertAfter=function(newEl,origin){
        var brotherElement=origin.nextElementSibling;
        if(brotherElement){
            var fatherEle=brotherElement.parentNode;
            fatherEle.insertBefore(newEl,brotherElement);
        }else{
            this.appendChild(newEl)
        }
    }

pageXOffset封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  判断pageXOffset是否存在,如果存在则返回不存在则将怪异模式和标准模式相加,因为两者只能存在其一

封装代码:

function getScrollOffset(){
    if(window.pageXOffset){
        return{
            left:window.pageXOffset,
            top:window.pageYOffset,
        }
    }else{
        return{
            left:document.body.scrollLeft+document.documentElement.scrollLeft,
            top:document.body.scrollTop+document.documentElement.scrollTop
        }
    }
}

innerWidth封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  判断innerWidth是否存在,如果存在则返回不存在则将通过compatMode判断怪异模式和标准模式,

然后分别返回

封装代码:

function getViewportSize(){
    if(window.innerWidth){
        return{
            width:window.innerWidth,
            height:window.innerHeight
        }
    }else{
        if(document.compatMode==='BackCompat'){
            return{
                width:document.body.clientWidth,
                height:document.body.clientHeight
            }
        }else{
            return{
                width:document.documentElement.clientWidth,
                height:document.documentElement.clientHeight
            }
        }
    }
}

scrollWidth封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  用于没有常规访问方式只有IE访问方式,所以直接判断第一个形式是否存在,不存在返回第二个

封装代码:

function getScrollSize(){
    if(document.body.scrollWidth){
        return{
            width:document.body.scrollWidth,
            height:document.body.scrollHeight
        }
    }else{
        return{
            width:document.documentElement.scrollWidth,
            height:document.documentElement.scrollHeight
        }
    }
}

offsetLeft封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  因为offsetLeft在寻找距离时,如果父级有定位则计算与父级的距离,所以要通过offsetParent去判断是否有父级定位,不断循环去累加与父级的距离

封装代码:

function getElemDocPosition(el){
    var parent=el.offsetParent,
        offsetLeft=el.offsetLeft,
        offsetTop=el.offsetTop;
        while(parent){
            offsetLeft+=parent.offsetLeft;
            offsetTop+=parent.offsetTop;
            parent=parent.offsetParent;
        }
        return {
            left:offsetLeft,
            top:offsetTop
        }
}

window.getCoumputedStyle封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  判断getCoumputedStyle是否存在 否则反之使用currentStyle,记得还要判断是否有prop

封装代码:

function getStyles(elem,prop){
        if(window.getComputedStyle){
            if(prop){
                return window.getComputedStyle(elem,null)[prop];
            }else{
                return window.getComputedStyle(elem,null);
            }

        }else{
             if(prop){
                return elem.currentStyle[prop];
            }else{
                return elem.currentStyle;
            }
        }
     }

 

elem.attachEvent封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  判断addEventListener是否存在 否则反之使用attachEvent,但是由于指向问题记得用call改变,

封装代码:

function attachEvent(event,fn,bubble){
    if(event.addEventListener){
            event.addEventListener(event,fn,bubble);
    }else if(event.attachEvent){
        event.attachEvent('on'+event,function(){
            fn.call(elem);
        })
    }else{
        event['on'+event]=fn;
    }

}

e.stopPropagation封装

封装理由:

  因为在不同浏览器的支持方式不同,故作兼容

封装思路:

  判断stopPropagation是否存在 否则反之使用cancleBubble,但是由于e指向问题记得用在开始判断,

封装代码:

function removeBubble(e){
    var e=e||window.event;
    if(e.stopPropagation()){
           e.stopPropagation()
    }else{
       e.cancelBubble=true;
    }

}

更多封装代码请查看以往DOM文章内

常见练习代码
 

要求:

  在原型上编程,遍历任何一个父元素,找到子元素的节点。接收参数,有参数则为对应的子元素,没有则打印子元素集合

Element.prototype.findChildren=function (argument,child,childArr) {
            var child=child||this.childNodes;
            var childArr=childArr||{},
            str=Object.prototype.toString;
             if(argument){
                for (var i = 0; i < child.length; i++) {
                    if (child[i].hasChildNodes()) {
                        if(argument===child[i].nodeType){
                         childArr[str.call(child[i])]= child[i];
                         }
                        arguments.callee(argument,child[i].children,childArr);
                    }else{
                       if(argument===child[i].nodeType){
                         childArr[str.call(child[i])]= child[i];
                       }
                    }
                };
                return childArr;
             }else{
                for (var i = 0; i < child.length; i++) {
                    if (child[i].hasChildNodes()) {
                         childArr[str.call(child[i])]= child[i];
                        arguments.callee(argument,child[i].children,childArr);
                    }else{
                         childArr[str.call(child[i])]= child[i];
                    }
                };
                 return childArr;
            }
         }
    var divC=document.getElementsByClassName('c')[0];
    var child= divC.findChildren();
    console.log(child);

要求:
 

在原型上编程,找出一个元素的第N层父级元素

Element.prototype.finFather=function(rank){
          var father=this.parentNode,
              fatherArr={},
              i=1;
          while(father.toString()!='[object HTMLBodyElement]') {
                fatherArr[i]=father.toString();
                father=father.parentNode;
                i++;
          };

          return fatherArr[rank];

    }


 

要求:

  原型上编程,判断父元素有没有子节点

 Element.prototype.isChild=function(){
        var child=this.childNodes;
        for (var i = 0; i < child.length; i++) {
            if(child[i].nodeType===1){
             return true;
            }
        };

        return false;
    }

要求:

  用js代码创建结构

 

var oDiv=document.createElement('div');
    oDiv.id='box';
    document.body.appendChild(oDiv);
    var oUl=document.createElement('ul');
    oUl.className='list';
    oDiv.appendChild(oUl);
    var oLi=document.createDocumentFragment();
    for (var i = 1; i <=5; i++) {
        var li=document.createElement('li');
        li.className='list-item';
        li.innerHTML=i;
        oLi.appendChild(li);
    };
    oUl.appendChild(oLi);

 

要求:

  将结构循环出来递归

 Element.prototype.foEachElement=function(element,elementArr){
        var element=element||this.childNodes,
            elementArr=elementArr||{};
        for (var i = 0; i < element.length; i++) {
            elementArr[i+element[i].toString()]=element[i];
            if(element[i].hasChildNodes()){
                elementArr[i+element[i].toString()]=element[i];
                arguments.callee(element[i].childNodes,elementArr);
            }else{
                  elementArr[i+element[i].toString()]=element[i];
            }

        };
        return elementArr;
    }

要求

  将子元素逆序

 <div>

<p></p>

<h1></h1>

<a href=""></a>

<div>

 Element.prototype.reverse=function(){
        var child=this.children;
        for (var i = child.length; i>0; i--) {
            this.appendChild(child[i-1]);
        };
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值