18.DOM进阶

DOM进阶html

学习要点:
1.DOM类型
2.DOM扩展
3.DOM操做内容node

DOM自身存在不少类型,在DOM基础课程中大部分都有所接触,好比Element类型,表示的是元素节点,再好比
Text类型:表示的是文本节点。DOM也提供了一些扩展功能。c++

1、DOM类型
DOM基础课程中,咱们了解了DOM的节点而且了解怎么查询和操做节点,而自己这些不一样的节点,又有着不一样的
类型。浏览器

DOM 类型
类型名 说明
Node 表示全部类型值的统一接口,IE不支持
Document 表示文档类型
Element 表示元素节点类型
Text 表示文本节点
Comment 表示文档中的注释类型
CDATASection 表示CDATA区域类型
DocumentType 表示文档声明
DocumentFragment 表示文档片断类型
Attr 表示属性节点类型服务器

 

1.Node类型
Node接口是DOM1级就定义了,Node接口定义了12个数值常量以表示每一个节点的类型值,除了IE以外,全部
浏览器均可以访问这个类型。app

Node的常量
常量名 说明 nodeType值
ELEMENT_NODE 元素 1
ATTRIBUTE_NODE 属性 2
TEXT_NODE 文本 3
CDATA_SECTION_NODE CDATA 4
ENTITY_REFERENCE_NODE 实体参考 5
ENTITY_NODE 实体 6
PROCESSING_INSIRUCETION_NODE 处理指令 7
COMMENT_NODE 注释 8
DOCUMENT_NODE 文档根 9
DOCUMENT_TYPE_NODE doctype 10
DOCUMENT_FRAGMENT_NODE 文档片断 11
NOTATION_NODE 符号 12dom

虽然这里介绍了12种节点对象的属性,用的多的其实也就几个而已。
alert(Node.ELEMENT_NODE); //1.元素节点类型值
alert(Node.TEXT_NODE); //2.文本节点类型值函数

咱们建议使用Node类型的属性来代替1,2这些阿拉伯数字,有可能你们会以为这样岂不是很繁琐吗?而且还有一个
问题就是IE不支持Node类型。性能

若是只有两个属性的话,用1,2来代替会特别方便,但若是属性特别多的状况下,1,2,3,4,5,6,7,8,9,10,11,12,
你根本就分不清那个数字表明的是哪一个节点,固然,若是你只用1,2两个节点,那就另当别论了。学习

IE不支持,咱们能够模拟一个类,让IE也支持。
if(typeof Node == 'undefined'){ //IE返回
window.Node ={
ELEMENT_NODE : 1,
TEXT_NODE : 3
};
}

2.Document类型
Document类型表示文档,或文档的根节点,而这个节点时隐藏的,没有具体的元素标签。
document; //document
document.nodeType; //9,类型值
document.childNodes[0]; //DocumentType,第一个子节点对象,IE理解为注释
document.childNodes[0].nodeType; //非IE为10,IE为8
document.childNodes[0].nodeName; //火狐为HTML,谷歌为html,IE为#comment
document.childNodes[1]; //HTML.HtmlElement
document.childNodes[1].nodeType; //HTML

若是想直接获得<html>标签的元素节点对象HTML.HtmlElement,没必要使用childNodes属性这么麻烦,可使
用documentElement便可。

document.documentElement; //HTML.HtmlElement

在不少状况下,咱们并不须要获得<html>标签的元素节点,而须要获得更经常使用的<body>标签,以前咱们采用的
是:document.getElementsByTagName('body')[0],,那么这里提供了一个更简便的方法:document.body

document.body; //HTML.BodyElement

在<html>以前还有一个文档声明;<!DOCTYPE>会做为某些浏览器的第一个节点来处理,这里提供一个简便
方法来处理:document.dctype。
document.doctype; //DocumentType

PS:IE8中,若是使用子节点访问,IE8以前会解释为让注释类型Comment节点,而document.doctyoe则会返回
null。
document.childNodes[0].nodeName //IE会是#Comment

在Document中有一些遗留的属性和对象合集,可使用的帮助咱们精确的处理一些任务。


//属性
document.title; //获取和设置<title>标签的值
document.URL; //获取URL路径
document.domain; //获取域名,服务器端
document.referrer; //获取上一个URL,服务器端


//对象合集
document.anchors; //获取文档中带name属性的<a>元素集合
document.links; //获取文档中带href属性的<a>元素集合
document.applets; //获取文档中<applet>元素集合,已不用
document.forms; //获取文档中<form>元素集合
document.images; //获取文档中<img>元素集合

3.Element类型
Element类型用于表现HTML中的元素节点,在DOM基础那章,咱们已经能够对元素节点进行查找、建立等操做
元素节点的nodeType为1,nodeName为元素的标签名。
元素节点对象在IE浏览器能够返回它具体元素节点的对象类型。

元素对应类型表

元素名 类型
HTML HTML.HtmlElement
DIV HTML.DivElement
BODY HTML.BodyElement
p HTML.ParamElement

PS:以上给出了部分对应,更多的元素对应类型,直接访问调用便可。

 

4.Text类型
Text类型用于表现文本节点类型,文本不包含HTML,或包含转义后的HTML。文本节点的nodeType为3。
在同时建立两个同一级别的文本节点的时候,会产生分离的两个节点。
var box = document.createElement('div');
var text = document.createTextNode('Mr');
var text2 = document.createTextNode('Lee');
box.appendChild(text);
box.appendChild(text2);
document.body.appendChild(box);
alert(box.childNodes.length); //2,两个文本节点


PS:把两个文本节点合并在一块儿使用normalize()便可
box.normalize(); //合并成一个节点

PS:有合并就有分离,经过splitText(num)便可实现节点分离。
box.firstChild.splitText(3); //分离一个节点,把前三个分离成新节点

除了上面的两种方法外,Text还提供了一些别的DOM操做的方法以下:
var box = document.getElementById('box');

box.firstChild.deleteData(0,2); //删除从0位置的2个字符
box.firstChild.insertData(0,'Hello'); //从0位置添加指定字符
box.firstChild.replaceData(0,2,'Miss'); //从0位置替换掉2个指定字符
box.firstChild.substringData(0,2); //从0位置获取2个字符,直接输出
alert(box.firstChild.nodeValue); //输出结果

 

5.Comment类型
Comment类型表示文档中的注释,nodeType是8,nodeName是#Comment,nodeValue是注释的内容。

var box = document.getElementById('box');
alert(box.firstChild); //Comment

PS:在IE中,注释节点可使用!号看成元素来访问。
var comment = document.getElementsByTagName('!');
alert(comment.length);


6.Attr类型
Attr类型表示文元素中的属性。nodeType为2,nodeName为属性名,nodeValue为属性值,DOM基础已经
详细介绍。

 

 


2、DOM扩展
1.呈现模式
从IE6开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE为document对象添加一个名为
compatMode属性。这个属性能够识别IE浏览器的文档处于什么模式,若是是标准模式,则返回CSS1Compat
,若是时混杂模式则返回BackCompat。
if(document.compatMode == 'CSS1Compat'){
alert(document.documentElement.clientWidth);
}else{
alert(document.body.clientWidth);
}

PS:后来Firefox、Opera和Chome都实现了这个属性。从IE8后,又引入了documentMode新属性,由于IE8
有3种呈现模式分别为标准模式8,仿真模式7,混杂模式5。因此若是想测试IE8的标准模式,就判断
document.documentMode > 7便可。

2.滚动
DOM提供了一些滚动页面的方法,以下:
document.getElementById('box').scrollIntoView(); //设置指定可见,将指定的节点滚动到可见范围


3.children属性
因为子节点空白问题,IE和其余浏览器解释不一致。虽然能够过滤掉,但若是只是想获得有效子节点,可使用
children属性,支持的浏览器为:IE5+、Firefox3.5+、Safari2+、Opera8+和Chrome,这个属性是非标准的。
var box = document.getElementById('box');
alert(box.children.length); //获得有效子节点数目,忽略掉了空白节点

 

4.contains()方法
判断一个节点是否是另外一个节点的后代,咱们可使用contains()方法,这个方法是IE率先使用的,开发人员无须
遍历便可获取此信息。
var box = document.getElementById('box');
alert(box.contains(box.firstChild)); //true

PS:早期的Firefox不支持这个方法,新版的支持了,其余浏览器也都支持,Safari浏览器支持的有问题,没法使
用,因此,必须作兼容。

function contains(refNode , otherNode){
if(typeof refNode.contains != 'undefined'){
return refNode.contains(otherNode);
}else if(typeof refNode.compareDocumentPosition == 'function'){
return refNode.compareDocumentPosition(otherNode) > 16;
}
}

 

在Firefox的DOM3级实现中提供了一个替代的方法compareDocumentPosition()方法。
这个方法肯定两个节点之间的关系。

var box = document.getElementById('box');
alert(box.compareDocumentPosition(box.firstChild)); //20,大于16就是包含关系

关系掩码表
掩码 节点关系
1 无关(节点不存在)
2 居前(节点在参考点以前)
4 居后(节点在参考点以后)
8 包含(节点是参考点的祖先)
16 被包含(节点时参考点的后代)

PS:为何会出现20,那是由于知足了4和16两项,最后相加了。为了能让全部浏览器均可以兼容,咱们必须
写一个兼容性的函数。

 

//传递参考节点(父节点),和其余节点(子节点)
function contains(refNode , otherNode){
//判断支持comtains,而且非Safari浏览器
if(typeof refNode.contains != 'undefined' && !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)){
return refNode.comment(otherNode);
//判断支持compareDocumentPosition的浏览器,大于16就是包含
}else if(typeof refNode.compareDocumentPosition == 'function'){
return !!(refNode.compareDocumentPosition(otherNode) > 16);
}else{
//更低的浏览器兼容,经过递归一个个获取他的父节点是否存在
var node = otherNode.parentNode;
do{
if(node == refNode){
return true;
}else{
node = node.parentNode;
}
}while (node != null);
}
return false;
}

 


3、DOM操做内容
虽然在以前咱们已经学习了各类DOM操做的方法,这里所介绍是innerText、innerHTML、otherText和otherHTML
等属性。除了以前用过的innerHTML以外。其余三个尚未涉及到。

1.innerText属性
document.getElementById('box').innerText; //获取文本内容(若有html直接过滤掉)
document.getElementById('box').innerText='Mr.Lee';//设置文本(若有html转义)


PS:除了Firefix以外,其余浏览器均支持这个方法。但Firefox的DOM3级提供了另一个相似的属性:
textCotent,作上兼容可通用。

document.getElementById('box').textContent; //Firefox支持

//兼容方案
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;
}
}

 

2.innerHTML属性
这个属性以前就已经研究过,不拒绝HTML。
document.getElementById('box').innerTHML; //获取文本(不过滤HTML)
document.getElementById('box').innerHTML = '<b>123</b>'; //可解析HTML

虽然innerHTML可插入HTML,但自己仍是有必定的限制,也就是所谓的做用域元素,离开这个做用域就无效了。
box.innerHTML = "<script>alert('Lee')</script>"; //<script>元素不能执行
box.innerHTML = "<style>background:red;</style>"; //<style>元素不能被执行

3.outerText
outerText在取值的时候和innerHTML同样,同时火狐不支持,而赋值方法至关危险,它不单替换了文本内容,
还将元素直接抹去。

var box = document.getElementById('box');
box.outerText = '<b>123</b>';
alert(document.getElementById('box')); //null,建议不去使用


4.outerHTML
outerHTML属性在取值和innerHTML一致,但和outerText也同样,很危险,赋值的以后将元素抹去。
var box = document.getElementById('box');
box.outerHTML = '123';
alert(document.getElementById('box')); //null,建议不去使用

PS:关于最经常使用的innerHTML属性和节点操做方法的比较,在插入大量HTML标记时使用innerHTML的效率明显
要高不少,由于在设置innerHTML时,会建立一个HTML解析器,这个解析器是浏览器级别的(c++编写的),
所以执行Javascript会快的多。但建立和销毁HTML解析器也会带来性能损失。最好控制在最合理的范围内,以下:
for(var i = o ; i<10 ; i++){
ul.innerHTML = '<li>inem<li>'; //避免频繁
}
//改
for(var i = 0 ; i<10; i++){
a = '<li>item<li>'; //临时保存
}
ul.innerHTML = a;


HTML5中新API:
按类名查找元素:IE8不支持
var elems=
document/parentNode.getElementsByClassName("类名")

按选择器查找元素:IE8支持!
按照选择器查找符合条件的元素:
var firstElem=document.querySelector("CSS选择器");
var elems=document.querySelectorAll("CSS选择器");
原生API:底层实现!

vs 旧getxxxByXXX方法
旧getxxxByXXX方法:返回仅是实际元素对象的引用。还须返回树结构中遍历对象的属性。
selectors API:返回结果包含完整的元素对象和属性。不须要再返回树中遍历,便可访问元素的全部属性!

DEMO:二级菜单弹出
onmouseover: 鼠标进入元素边界时,*发生一次*!
onmouseout: 鼠标移出元素边界时,触发一次

DOM树的快速得到指定节点:
document.documentElement: 整个<html>的内容——了解
document.body:直接得到body元素!——重要

*爬树:
向上爬:parentNode:
向下爬:querySelectorAll:*

元素树:节点树去掉属性节点和文本节点后获得的只有元素组成的树。
节点树 vs 元素树:
父节点 parentNode parentElementNode
全部子节点 childNodes children
第一个子节点 firstChild firstElementChild
最后子节点 lastChild lastElementChild
前一个兄弟 previousSibling previousElementSibling
后一个兄弟 nextSibling nextElementSibling

动态建立节点:3步:1. 建立空节点:var newElem=document.createElement("标签名");好比:var a=document.createElement("a"); <a></a>2. 设置节点对象必要属性:好比:a.href="http://tmooc.cn";a.innerHTML="tmooc"; <a href="http://tmooc.cn">tmooc</a>*************************3. 将节点挂到指定父元素下*//向父元素末尾追加新元素parentNode.appendChild(newElem);//在父元素中间,插入新元素parentNode.insertBefore(newElem,后一个现有元素对象)

相关文章
相关标签/搜索