兼容问题不考虑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)innerHTML、outerHTML 这两个属性适用于“给文档插入大量新HTML标记”的情景。在写模式下,它的值会被解析为DOM树。局限:不适用于插入<script>元素(程序不会执行)。具有性能问题,要避免频繁操作,建议单独创建字符串并一次性赋值。
(4)innerText、outerText 可过滤掉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) firstChild 、lastChild 获取首个、最后个子节点(包括文本、注释)
(3) nextSibling、previousSibling 获取兄弟节点(包括文本、注释)
(4) children 返回一个子元素节点的HTMLCollection实例(用childElementCount可以获取子元素数目) (不包含文本、注释)
(5) firstElementChild、lastElementChild (不包括文本、注释)
(6) nextElementSibling、previousElementSibling (不包括文本、注释)
(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.archors、document.images、document.forms、document.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);
}
}
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) nodeName、nodeType、nodeValue 分别返回节点名(元素是标签名、特性则是特性名)、节点类型、节点值(文本则是文本内容)。
2、文档的属性
(1) document.title 返回文档的标题
(2) document.URL、document.domain、document.referer分别返回url地址、主机名和上一级的地址。其中document.domain可以在一定程度解决跨域。
(3) document.readyState 返回文档的加载状态。
(4) document.compatMode 返回当前文档处于标准模式还是混杂模式。
(5) document.charset 属性可设置或返回被链接资源的字符集。
(6) document.defaultView 文档的归属window对象
3、元素的属性
(1) tagName、id、title、lang 分别返回元素节点的标签名以及公认特性(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) offsetHeight、offsetWidth、offsetLeft、offsetTop 、offsetParent
这五个元素属性是只读的。offsetParent 是最近的并且是定位过(relative,absolute)的父元素(最外层是body)。
(5) clientWidth、clientHeight
(6) scrollHeight、scrollWidth、scrollLeft、scrollTop 、scrollParent
滚动大小scrollHeight、scrollWidth用于确定元素内容的实际大小。
滚动页面的总高度是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也完全相同,但两个节点可以是引用两个对象。
网友评论