美文网首页
DOM API 详细总结和兼容方法

DOM API 详细总结和兼容方法

作者: 汤汤汤不乐 | 来源:发表于2019-02-07 21:50 被阅读0次

    兼容问题不考虑IE9之前

    DOM中的节点类型和对应的nodeType值:
    Element (1) :元素节点。[可有子节点]
    Attr (2) :特性节点。
    Text (3) :文本节点。
    Comment (8):注释节点。
    Document (9):文档节点。[可有子节点(有限)]
    DocumentType (10):文档类型声明节点。
    DocumentFragment (11): 文档片段节点。[可有子节点]

    一、节点创建

    1、创建元素节点

    document.createElement() 是最常用的,用于创建一个新的元素节点。且在所有主流浏览器中都支持。

    var div = document.createElement('div');  // 创建一个div节点
    
    2、克隆节点

    (1) document.cloneNode() 适用于所有节点类型。有两种克隆方式:深复制可以得到包含的子节点,浅复制不能得到子节点。该方法只会复制特性,而不会复制事件。在IE中会复制事件处理程序,所以建议:复制前最好先移除事件处理程序。

    var deepList = myList.cloneNode(true);  //深复制
    

    (2) document.impotNode() 把一个节点从另一个文档复制到该文档以便应用。

    3、创建文本节点和文档写入

    (1)document.createTextNode() 只创建一个文本节点,就算传入的字符串中包含html标签也不会被解析而是被当做文本字符。
    (2)document.write()document.writeIn() 会将传入的字符串原样写入文档(后者会换行)。注意:在页面加载之后调用会重写页面。该方法是文档对象document的一个方法,因此不能在特定节点里写入内容,有一定局限性。
    (3)innerHTMLouterHTML 这两个属性适用于“给文档插入大量新HTML标记”的情景。在写模式下,它的值会被解析为DOM树。局限:不适用于插入<script>元素(程序不会执行)。具有性能问题,要避免频繁操作,建议单独创建字符串并一次性赋值。
    (4)innerTextouterText 可过滤掉HTML标签后生成一个子文本节点。在写模式下,会替换容器内所有内容。建议不适用outerText,会使得原元素不存在。
    (5)insertAdjacentHTML() 有四类参数:beforebegin、afterbegin、beforeend、afterend。

    // 作为前一个同辈元素插入
    element.insertAdjacentHTML("beforebegin","<p>hello</p>");
    

    (6)兼容性
    innerHTML 能支持所有浏览器,除了有些元素本身就不能使用外,还有些元素(比如table相关)会出现在IE9中不能执行写操作的情况,网上兼容方法可供参考:

    // 兼容IE:table.InnerHTML写模式 代码来源于网络
    // 注意传入的html中包含<tbody>标签
    function setTableInnerHTML(table, html) {
      if (navigator && navigator.userAgent.match(/msie/i)) {  
        var temp = table.ownerDocument.createElement('div');
        temp.innerHTML = '<table><tbody>' + html + '</tbody></table>';
        if (table.tBodies.length == 0) {   
          var tbody = document.createElement("tbody");
          table.appendChild(tbody);
        }
        table.replaceChild(temp.firstChild.firstChild, table.tBodies[0]);
      } else {
        table.innerHTML = html;
      }
    }
    

    outerHTML 在火狐7之前不支持。虽然火狐是自动更新的,但也可以用以下方式替换这个属性的写功能:

    // 与outerHTML能力相同
    var p = document.createElement("p");
    p.appendChild("要加入的字符串");
    div.parentNode.replaceChild(p,div);
    

    innerText:火狐不支持,但是有textContent属性。兼容方法:

    // 兼容火狐:innerText
    function getInnerText(element){
        return (typeof element.textContent == "string") ? element.textContent : element.innerText ;
    }
    
    function setInnerText(element, text){
        if (typeof element.textContent == "string"){
              element.textContent = text;
        } else {
              element.innerText = text;
        }
    }
    
    4、表格元素的特殊创建方式
    // 创建table
    var table = document.createElement("table");
    table.border = 1;
    table.width = "100%";
    
    // 创建tbody
    var tbody = document.createElement("tbody");
    table.appendChild(tbody);
    
    // 创建第一行
    tbody.insertRow(0);
    tbody.row[0].insertCell(0);
    tbody.row[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
    tbody.row[0].insertCell(1);
    tbody.row[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
    
    // 创建第二行
    tbody.insertRow(1);
    tbody.row[1].insertCell(0);
    tbody.row[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
    tbody.row[1].insertCell(1);
    tbody.row[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
    
    // 将表格添加到文档主体
    document.body.appendChild(table);
    
    5、其他节点的创建

    (1)document.createDocumentFragment() 可以创建文档片段,包含和控制节点,可以用于暂时保存节点,再一次性加入文档。所有浏览器支持。
    (2)document.createComment() 可以创建注释节点。

    二、节点获取

    1、获取子节点、父节点、兄弟节点

    (1) childNodes 返回一个子节点的NodeList实例(包括文本、注释)
    (2) firstChildlastChild 获取首个、最后个子节点(包括文本、注释)
    (3) nextSiblingpreviousSibling 获取兄弟节点(包括文本、注释)
    (4) children 返回一个子元素节点的HTMLCollection实例(用childElementCount可以获取子元素数目) (不包含文本、注释)
    (5) firstElementChildlastElementChild (不包括文本、注释)
    (6) nextElementSiblingpreviousElementSibling (不包括文本、注释)
    (7) parentNode 可以获取节点的父节点。父节点只有一个。

    2、获取元素节点

    (1) document.getElementById() 根据id获取元素节点
    (2) getElementsByTagName()根据标签名获取元素节点的DOM集合。返回一个HTMLCollection实例。(文档、元素皆可调用)
    (3) getElementsByName() 根据name特性返回元素节点集合。需要区别的是通过getElementsByTagName().namedItem()只返回第一项。(文档、元素皆可调用)
    (4) getElementsByClassName() [HTML5扩展] 返回带有指定类的所有元素的HTMLCollection实例。(文档、元素皆可调用)
    (5) querySelector()querySelectorAll() 根据接收的CSS选择符获取元素节点。(文档、元素皆可调用,如果是集合返回NodeList实例)
    (6) document.archorsdocument.imagesdocument.formsdocument.links 分别获取文档中带name的<a>元素、所有<img>元素、<form>元素、带href的<a>元素。

    3、获取特性节点和修改特性

    (1) getAttribute() 建议用此方法获取标签自定义的特性,而公认特性用属性的方式获取,尤其是style、onclick。用 setAttribute()可 添加和设置特性。 用removeAttribute()移除特性(此处要区分哪些是DOM属性、哪些是标签特性、哪些特性是能作为属性获取)
    (2) element.style是一个CSSStyleDeclaration的实例,包含style特性指定的样式信息。 element.style.cssText获得特性的字符串表示。使用window.getComputedStyle()可以同时获得style特性指定的以及从其他样式表中层叠而来的样式。(所有的计算样式是只读的,且在浏览器中表现各异)。
    (3) className 返回元素的class特性值(字符串)。
    (4) classList 返回DOMTokenList的实例,通过这个集合能够操作元素的类名(add、contains、remove、toggle)
    不兼容IE9。兼容方法:
    原文链接:http://caibaojian.com/classlist.html

    function hasClass(obj, cls) { 
     return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); 
    } 
     
    function addClass(obj, cls) { 
     if (!this.hasClass(obj, cls)) obj.className += " " + cls; 
    } 
     
    function removeClass(obj, cls) { 
     if (hasClass(obj, cls)) { 
     var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); 
     obj.className = obj.className.replace(reg, ' '); 
     } 
    } 
     
    function toggleClass(obj,cls){ 
     if(hasClass(obj,cls)){ 
     removeClass(obj, cls); 
     }else{ 
     addClass(obj, cls); 
     } 
    }
    

    或者:跨浏览器javascript shim·

    4、获取特殊的对象

    (1) document.activeElement 属性返回文档中当前获得焦点的元素,用 document.hasFocus 返回当前文档是否获取了焦点。
    (2)document.head 返回当前文档的<head>元素。
    (3)document.body 返回当前文档的<body>元素。
    (4)document.documentElement 返回当前文档的<html>元素。
    (5)文本和注释节点可以用子节点的方式获取
    (6) iframe.contentDocument 可用来获取框架的文档对象。iframe.contentWindow可用来获取框架的窗口对象。

    三、获取属性

    1、节点的属性

    (1) ownerDocument 返回节点所在的文档
    (2) nodeNamenodeTypenodeValue 分别返回节点名(元素是标签名、特性则是特性名)、节点类型、节点值(文本则是文本内容)。

    2、文档的属性

    (1) document.title 返回文档的标题
    (2) document.URLdocument.domaindocument.referer分别返回url地址、主机名和上一级的地址。其中document.domain可以在一定程度解决跨域。
    (3) document.readyState 返回文档的加载状态。
    (4) document.compatMode 返回当前文档处于标准模式还是混杂模式。
    (5) document.charset 属性可设置或返回被链接资源的字符集。
    (6) document.defaultView 文档的归属window对象

    3、元素的属性

    (1) tagNameidtitlelang 分别返回元素节点的标签名以及公认特性(id、title、lang)
    (2) dir 返回文字的方向
    (3) dataset 返回自定义的标签特性的对象。html5规定自定义的特性要以"data-"为前缀。该属性的兼容性不乐观:需要IE11+。兼容方法参考:

    function getDataset(ele){
        if(ele.dataset){
            return ele.dataset;
        }else{
            var attrs = ele.attributes,//元素的属性集合
                dataset = {}, name, matchStr;
            for(var i = 0;i<attrs.length;i++){ //是否是data- 开头
                matchStr = attrs[i].name.match(/^data-(.+)/);
                if(matchStr){ //data-auto-play 转成驼峰写法 autoPlay
                     name = matchStr[1].replace(/-([\da-z])/gi,function(all,letter){
                         return letter.toUpperCase(); });
                     dataset[name] = attrs[i].value;
                }
            }
            return dataset;
        }
    }
    
    var date_set = getDataset(element)
    console.log('dataset',date_set);
    console.log('dataset.src',date_set.src);
    

    (4) offsetHeightoffsetWidthoffsetLeftoffsetTopoffsetParent

    偏移量示意图
    这五个元素属性是只读的。offsetParent 是最近的并且是定位过(relative,absolute)的父元素(最外层是body)。

    (5) clientWidthclientHeight

    客户区大小示意图.png

    (6) scrollHeightscrollWidthscrollLeftscrollTopscrollParent

    滚动大小
    scrollHeightscrollWidth用于确定元素内容的实际大小。
    滚动页面的总高度是document.documentElement.scrollHeight
    页面的视口大小是document.documentElement.clientHeight

    (7)getBoundingClientRect() 返回一个矩形对象(DOMRect对象),包含left、top、right、bottom 4个属性。这些属性给出了元素在视口中的位置。

    var box=document.getElementById('box');         // 获取元素
    alert(box.getBoundingClientRect().top);         // 元素上边距离页面上边的距离
    

    四、节点操作

    1、节点的放置、替换和删除

    (1) appendChild()
    插入成为最后的子节点。

    element.appendChild(newListItem); 
    

    (2) insetBefore()
    插入一个子节点。

    // 插入成为最后的子节点
    someNode.insertBefore(newNode,null);
    // 插入成为第一个子节点
    someNode.insertBefore(newNode,someNode.firstChild);
    // 插入到最后一个子节点前面
    someNode.insertBefore(newNode,someNode.lastChild);
    

    (3) replaceChild()
    将某个子节点替换为另外一个。

    someNode.replaceChild(newnode,oldnode);
    

    (4) removeChild()
    删除某一个节点。

    list.removeChild(list.childNodes[0]);
    
    2、元素节点的操作

    (1) 通过元素的特性、style对象、className 、classList、元素属性中元素的大小等方式操作。
    (2) matchesSelector 检测是否为被指定的选择器字符串选择。一些浏览器需要加前缀来实现。替换方案:

    if (!Element.prototype.matches) {
        Element.prototype.matches = 
            Element.prototype.matchesSelector || 
            Element.prototype.mozMatchesSelector ||
            Element.prototype.msMatchesSelector || 
            Element.prototype.oMatchesSelector || 
            Element.prototype.webkitMatchesSelector ||
            function(s) {
                var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                    i = matches.length;
                while (--i >= 0 && matches.item(i) !== this) {}
                return i > -1;            
            };
    }
    // 如果元素被指定的选择器字符串选择,element.matches(str)  方法返回true; 否则返回false。
    
    3、文本节点的文本操作

    (1) normalize() 文本节点规范化。normalize() 方法移除空的文本节点,并连接相邻的文本节点。

    textNode.normalize()
    

    (2) 通过data属性操作。

    4、节点判断

    (1) compareDocumentPosition() 两个方法可用于判断两个节点的位置关系。

    var result = p1.compareDocumentPosition(p2);
    /* 返回值掩码:
    1:没有关系,两个节点不属于同一个文档。
    2:第一节点(P1)位于第二个节点后(P2)。
    4:第一节点(P1)定位在第二节点(P2)前。
    8:第一节点(P1)位于第二节点内(P2)。
    16:第二节点(P2)位于第一节点内(P1)。
    32:没有关系,或是两个节点是同一元素的两个属性。
    */ 
    // 如果p1包含p2
    alert( !!( result&16 ) )  // true
    

    (2) contains() 可以判节点的包含关系

    node.contains( otherNode )
    

    (3) isEqualNode() 判断两个节点是否相等。所谓相等,是指具有相同的属性,而且它们的attritubes与childNodes也完全相同,但两个节点可以是引用两个对象。

    相关文章

      网友评论

          本文标题:DOM API 详细总结和兼容方法

          本文链接:https://www.haomeiwen.com/subject/epbvsqtx.html