美文网首页
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 详细总结和兼容方法

    兼容问题不考虑IE9之前 DOM中的节点类型和对应的nodeType值:Element (1) :元素节点。[可有...

  • 十至十二章导读题

    10.1 什么是DOM?DOM是针对HTML和XML文档的一个API; 10.2在确定节点类型时,如何确保兼容性?...

  • etcd查询所有key

    etcd2和etcd3是不兼容的,两者的api参数也不一样,详细请查看 etcdctl -h api2 使用方法E...

  • 进阶篇:jQuery介绍 & 选择器(19)

    饥人谷学习进阶第 19 天 jQuery API 中文文档 为什么要用jQuery DOM API 难用 存在兼容...

  • DOM常用API

    Javascript操作DOM常用API总结 文本整理了javascript操作DOM的一些常用的api,根据其作...

  • 「DOM 编程」事件

    DOM 事件事件流事件注册注册事件取消事件触发事件浏览器兼容型兼容低版本代码实现事件对象属性和方法通用属性和方法阻...

  • jQuery的没落和技术发展的一般规律

    jQuery的成就 jQuery是一个伟大的库, 它解决了dom api兼容的问题,使得dom操作更简便 它支持类...

  • 兼容的 DOM 方法

    1. 获取某个容器中所有的元素(也可以获取特定标签的元素)(children) 2. getElementsByC...

  • dom

    Javascript操作DOM常用API总结 Posted on 2015-11-30 | In Ja...

  • Dom基础1

    DOM基础 DOM简介、DOM标准、DOM节点 获取元素的子节点:childNodes、兼容性问题火狐不兼容,可以...

网友评论

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

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