什么是DOM?
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(增删改查)。通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素。DOM 使 JavaScript 有能力对 HTML 事件做出反应。
DOM 树
浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。
节点 node
DOM的最小组成单位就是node。档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
节点的7种类型
Document:整个文档树的顶层节点
DocumentType:doctype标签(比如)
Element:网页的各种HTML标签(比如
Attribute:网页元素的属性(比如class="a" src='img/a.png')
Text:标签之间或标签包含的文本
Comment:注释
DocumentFragment:文档的片段 //不常用
Text类型
文本节点由Text 类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的
HTML 字符,但不能包含HTML 代码。Text 节点具有以下特征:
nodeType 的值为3;
nodeName 的值为”#text”;
nodeValue 的值为节点所包含的文本;
parentNode 是一个Element;
不支持(没有)子节点。
扩展:获取文本内容
1 .innerHTML
从对象的起始位置到终止位置的全部内容,包括Html标签。
innerHTML可以作为获取文本的方法也可以作为修改文本内容的方法
element.innerHTML 会直接返回element节点下所有的HTML化的文本内容
!注意 innerHTML方法只能作用于元素节点调用;文本节点并不能使用这个方法返回undefined
innerText 与 innerHtml 都是打印标签之间的文本信息
1、innerText 打印标签之间的纯文本信息,会将标签过滤掉,低版本的火狐浏览器不支持,而是支持textContent
2、innerHtml 打印标签之间的内容,包括标签和文本信息,各浏览器都支持,但是高版本的浏览器会原样打印
innerText 与 innerHtml不仅在获取元素文本上有区别,而且在设置上同样有区别。
1、innerText 在设置HTML标签时,会将<>进行转义,在输出的时候会原样输出,并不会解析HTML标签
2、innerHtml 在设置HTML标签时,浏览器会将HTML标签名解析成对应的标签
2.3 textContent
textContent与innerHTML方法类似会返回对象节点下所有的文本内容
但是区别为 textContent返回的内容只有去HTML化的文本节点的内容 如上例:
document.body.textContent //返回"文本文本" !注意在DOM中标签换行产生的空白字符会计入DOM中作为文本节点
另外IE8以前不支持textContent属性
2.4 innerText
从起始位置到终止位置的内容, 但它去除Html标签
innerText方法与textContent方法类似 并且和innerHTML一样也是作用于元素节点上
但是浏览器对于这两种方法解析空白字符的机制不一样;不是很常用
类似的还有outText outHTML等类似操作文本相关的方法
outerHTML 设置或获取对象及其内容的 HTML 形式
除了包含innerHTML的全部内容外, 还包含对象标签本身。
outerText 设置(包括标签)或获取(不包括标签)对象的文本
最后要提醒一点:文本与文本节点一定要区分,有些方法是依靠元素节点返回子文本内容,有些方法是文本节点返回自身文本内容,文本节点是对象而文本只是字符串;
innerHTML是符合W3C标准的属性,而innerText只适用于IE浏览器
注意:浏览器在解析节点中空白符时,会把它当作文本节点。因为浏览器的差异在对于非空文本节点前面或后面有空格或换行符等特殊的文本字符组成,IE和FF就会产生分歧,IE会忽略这些节点,而FF则认可这些节点。分歧产生的原因是FF认为
- 和
由于元素书写时存在空白换行符等,所以导致在操作DOM节点出现问题,所以在遍历子节点时应该对文本节点做特殊处理,可以利用Document类型的nodeType属性过滤文本节点:
例:根据NodeType来判断:var td = document.getElementById("TEST");
var childs=[],i,len,node;
for(i=0,len=td.childNodes.length;i
//过滤文本节点
if(node.nodeType!=3){
childs.push(node);
}
}
alert(childs.length); //结果为2
节点的属性:
nodeType
nodeType属性返回一个整数值,表示节点的类型。
文档节点(document):9
元素节点(element):1
属性节点(attribute):2
文本节点(text):3
文档片断节点(DocumentFragment):11
文档类型节点(DocumentType)10
注释节点(Comment):8,
nodeName
nodeName 返回节点的名称
文档节点(document):#document
元素节点(element):大写的标签名
属性节点(attr):属性的名称
文本节点(text):#text
文档片断节点(DocumentFragment):#document-fragment
文档类型节点(DocumentType):文档的类型
注释节点(Comment):#comment
nodeValue
nodeValue 返回节点的文本值,可读可写
nodeValue是一个HTML DOM的对象属性;
同样的 可以通过 nodeValue设置节点的文本内容也可以直接返回文本内容
直接用节点对象调用就都可以: 如上例
document.getElementsByTagName(div)[0].childNodes[0].nodeValue //返回“文本”
另外 nodeValue 属性并不只存在于文本节点下 元素节点和属性节点对象也都具有nodeValue属性
属性节点的 nodeValue属性返回属性值
元素节点的 nodeValue属性返回null
节点的属性 textContent 返回当前节点和他所有后代节点的文本。忽略标签。
例:
document.getElementById('div').textContent //我是span
同样textContent也是一个可读可写的属性。如果写入的内容包含标签, 也会把标签当做文本。
例:div.textContent='
我是p
'nextSibling:
nextSibling 返回当前节点的下一个兄弟节点
例:
var div1 = document.getElementById('d1');
div1.nextSibling
sibling:就是兄弟的意思
next:下一个的意思
previous:前一个的意思
如果不存在下一个兄弟节点则返回null
a、下一个兄弟节点=节点.nextElementSibling || 节点.nextSibling
①.nextSibling: 调用者是节点在IE678中指下一个元素节点(标签),在火狐谷歌IE9+以后都指的是下一个节点(包括空文档和换行节点).
②. nextElementSibling:在火狐谷歌IE9都指的是下一个元素节点
总结:在IE678中用nextSibing,在火狐谷歌IE9+以后用nextElementSibing
perviousSibling:
b、前一个兄弟节点=节点.previousElemnentSibling || 节点.previousSibling
①. previousSibling:调用者是节点,IE678中指前一个元素节点(标签).在火狐谷歌IE9+以后都指的是前一个节点(包括空文档和换行节点)
②. previousElementSibling:在火狐谷歌IE9都指的是下一个元素节点
总结:在IE678中用previousSibling,在火狐谷歌IE9+以后用previousElementSibling
firstchild:
3 单个子节点
a、第一个子节点=父节点.firstElementChild || 父节点.firstChild
①.first:调用者是父节点,IE678中指第一个子元素节点(标签).在火狐谷歌IE9+以后都指的是第一个节点(包括文档和换行节点)
②. firstElementChild:在火狐谷歌IE9都指的第一个元素节点
lastchild:
b、最后一个子节点=父节点.lastElementChild ||父节点.lastChild
①. lastChild:调用者是父节点,IE678中指最后一个子元素节点(标签),在火狐谷歌IE9+以后都指的是最后一个节点(包括空文档和换行节点)
②. lastElementChild:在火狐谷歌IE9+都指的是最后一个元素节点
childNodes:
所有子节点
a、子节点数组=父节点.childNodes 获取所有节点,是一个nodelist数据
ChildNodes:它是标准属性,他返回指定元素的子元素集合(返回当前所有的子节点),包括HTML节点 所有属性 文本节点 (它是W3C的亲儿子)
火狐 谷歌等高版本会把换行也看做是子节点
* ①.nodeType = 1 表示的是元素节点 记住 元素就是标签
* ②. nodeType = 2 表示属性节点
* ③. nodeType = 3 表示文本节点
- b、子节点数组=父节点.children; 用的最多
children:非标准属性,他只返回指定元素的子元素集合(返回当前所有的元素子节点),
但他只返回HTML节点,甚至不反悔文本节点,虽然不是标准的DOM属性,但他和innerHTML方法一样,得到了几乎所有浏览器的支持,
children 在IE678中包含注释节点,
在IETF78中,注释节点不要写在里面
节点自己.parentNode.children[index]; 随意得到兄弟节点
获取所有的兄弟节点
function siblings(elm){
var a=[ ];
var p=elm.parentNode.children;
for(var i=0;i
a.push(p[i]);
}
}
return a;
}
父节点(parentNode、parentElement)
parentNode,parentElement 区别
parentElement 和 parentNode一样,但parentNode是W3C标准的,而parentElement 只在IE中可用.
firstChild,lastChild,nextSibling,previousSibling都会将空格或者换行当做节点处理,但是有代替属性
所以为了准确地找到相应的元素,会用
firstElementChild,
lastElementChild,
nextElementSibling,
previousElementSibling
兼容的写法,这是JavaScript自带的属性。
但坏消息是IE6,7,8不兼容这些属性。IE9以上和火狐谷歌支持。