DOM
在 HTML DOM 中,所有事物都是节点。DOM 是被视为节点树的 HTML。
主要有以下几种DOM类型:
元素类型 | NodeType |
---|---|
元素 | 1 |
属性 | 2 |
文本 | 3 |
注释 | 8 |
文档 | 9 |
常用方法:
方法 | 描述 |
---|---|
getElementById() | 返回带有指定 ID 的元素。 |
getElementsByTagName() | 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。 |
getElementsByClassName() | 返回包含带有指定类名的所有元素的节点列表。 |
appendChild() | 把新的子节点添加到指定节点。 |
removeChild() | 删除子节点。 |
replaceChild() | 替换子节点。 |
insertBefore() | 在指定的子节点前面插入新的子节点。 |
createAttribute() | 创建属性节点。 |
createElement() | 创建元素节点。 |
createTextNode() | 创建文本节点。 |
getAttribute() | 返回指定的属性值。 |
setAttribute() | 把指定属性设置或修改为指定的值。 |
属性操作:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div style="color:black" id="box" title="mytitle" class="class" bbb="bbb_value">
hello
</div>
<input id="input" type="text" value="123"/>
<input id="input1" type="radio" checked/>
</body>
<script type="text/javascript">
document.getElementById('box').id;//获取id
//document.getElementById('box').id = 'person';//设置id
document.getElementById('box').title;//获取title
document.getElementById('box').title = 'new_title';//设置title
document.getElementById('box').style;//获取CSSStyleDeclaration对象
document.getElementById('box').style.color;//获取style对象中color的值
document.getElementById('box').style.color = 'red';//设置style对象中color的值
document.getElementById('box').className;//获取class
document.getElementById('box').className = 'box';//设置class
document.getElementById('box').getAttribute('className');//非IE不支持
console.log(document.getElementById('box').bbb);//获取自定义属性的值,非IE不支持
document.getElementById('box').setAttribute("bbb","new_bbb_value");
console.log(document.getElementById('box').getAttribute("bbb"));//new__bbb_value
document.getElementById('box').removeAttribute("bbb");//删除属性
console.log(document.getElementById('box').getAttribute("bbb"));//null
console.log(document.getElementById('input').value);//1234
console.log(document.getElementById('input1').checked);//true
</script>
</html>
节点层次:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div style="color:black" id="box" title="mytitle" class="class" bbb="bbb_value">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById('box')
console.log(div.innerHTML);
/*
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
*/
console.log(div.childNodes.length);//得到子节点个数,IE3个,非IE7个,换行会产生空白节点
console.log(div.childNodes[0].nodeValue);//输出空白
console.log(div.attributes['bbb'].nodeValue);//bbb_value
console.log(div.attributes.getNamedItem('bbb').nodeValue);//和上面效果一样
console.log(div.firstChild.nodeValue);//输出空白
console.log(div.firstChild.innerHTML);//undefined
console.log(div.lastChild.nodeValue);//输出空白
console.log(div.ownerDocument);//#document
console.log(div.childNodes[0].nextSibling.innerHTML);//hello1
console.log(div.childNodes[2].previousSibling.innerHTML);//hello2
console.log(div.parentNode);//body对象
</script>
</html>
注意:在获取到文本节点的时候,是无法使用innerHTML这个属性输出文本内容的。这个非标准的属性必须在获取元素节点的时候,才能输出里面包含的文本;在非IE中,标准的DOM具有识别空白文本节点的功能,所以在火狐浏览器是7个,而IE自动忽略了,如果要保持一致的子元素节点,需要手工忽略掉它。
节点操作:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
</body>
<script type="text/javascript">
document.write("<div id='box'></div>");
var span = document.createElement("span");
var text = document.createTextNode("hello");
span.appendChild(text);
document.getElementById("box").appendChild(span);
var h = document.createElement("h1");
var text1 = document.createTextNode("h1");
h.appendChild(text1);
document.getElementById("box").insertBefore(h,span);
var input = null;
input = document.createElement('input');
input.setAttribute('type', 'radio');
input.setAttribute('name', 'sex');
document.getElementById("box").appendChild(input);
//替换节点
var text2 = document.createTextNode("new_hello");
span.replaceChild(text2,span.childNodes[0]);
//克隆节点
var span1 = span.cloneNode(true);//true会复制内容,否则只复制结构
span1.id = "span1";
document.getElementById("box").appendChild(span1);
//删除节点
document.getElementById("box").removeChild(document.getElementById("span1"));
</script>
</html>
DOM扩展
呈现模式
从IE6开始开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE为document对象添加了一个名为compatMode属性,这个属性可以识别IE浏览器的文档处于什么模式如果是标准模式,则返回CSS1Compat,如果是混杂模式则返回BackCompat。
<script type="text/javascript">
if (document.compatMode == 'CSS1Compat') {
console.log(document.documentElement.clientWidth);
} else {
console.log(document.body.clientWidth);
}
</script>
后来Firefox、Opera和Chrome都实现了这个属性。从IE8后,又引入documentMode新属性,因为IE8有3种呈现模式分别为标准模式8,仿真模式7,混杂模式5。所以如果想测试IE8的标准模式,就判断document.documentMode > 7 即可。
滚动
scrollIntoView(alignWithTop) 函数用来滚动浏览器窗口或容器元素,以便在当前视窗的可见范围看见当前元素。如果alignWithTop为true,或者省略它,窗口会尽可能滚动到自身顶部与元素顶部平齐
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<a onClick="onc()" hef="#">click here</a>
<div style="height:400px; background-color:blue"></div>
<div id="nn" style="background-color: red;height:900px;"></div>
</body>
<script type="text/javascript">
//作为一个事件的函数来被调用
function onc () {
var dd = document.getElementById("nn").scrollIntoView(true);//这个意思其实就是将这个元素滚动到浏览器窗口的顶部来显示
}
</script>
</html>
children属性
由于子节点空白问题,IE和其他浏览器解释不一致。虽然可以过滤掉,但如果只是想得到有效子节点,可以使用children属性,几乎所有浏览器都支持。
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
console.log(document.getElementById("div").children.length);//3
console.log(document.getElementById("div").children[0].innerHTML);//hello1
</script>
</html>
contains()方法
判断一个节点是不是另一个节点的后代,我们可以使用contains()方法。这个方法是IE率先使用的,开发人员无须遍历即可获取此信息
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.contains(div.firstChild));//true
</script>
早期的Firefox不支持这个方法,新版的支持了,其他浏览器也都支持,Safari2.x浏览器支持的有问题,无法使用。所以,必须做兼容
在Firefox的DOM3级实现中提供了一个替代的方法compareDocumentPosition()方法。这个方法确定两个节点之间的关系。
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.compareDocumentPosition(div.firstChild));//20
</script>
innerText属性
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.innerText);//获取文本内容(如有html直接过滤掉)
div.innerText = 'Mr.Lee';//设置文本(如有html转义)
//DOM3新属性
console.log(div.textContent)
div.innerText = '<html>';
</script>
</html>
innerHTML属性
<script type="text/javascript">
document.getElementById('div').innerHTML;//获取文本(不过滤HTML)
document.getElementById('div').innerHTML = '<b>123</b>';//可解析HTML
</script>
虽然innerHTML可以插入HTML,但本身还是有一定的限制,也就是所谓的作用域元素,离开这个作用域就无效了
<script type="text/javascript">
document.getElementById("div").innerHTML = "<script>alert('Lee');</script"+">";//<script>元素不能被执行
</script>
outerText属性
outerText在取值的时候和innerText一样,但是赋值方法相当危险,他不单替换了文本内容,还将元素直接抹去。
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.outerText);//获取文本内容(如有html直接过滤掉)
div.outerText = 'Mr.Lee';//设置文本(如有html转义)
console.log(document.getElementById("div"));//null
</script>
</html>
outerHTML属性
outerHTML属性在取值和innerHTML一致,但和outerText也一样,很危险,赋值的之后会将元素抹去。
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.outerHTML);//获取文本内容(如有html直接过滤掉)
div.outerHTML = '<b>124</b>';//设置文本(如有html转义)
console.log(document.getElementById("div"));//null
</script>
关于最常用的innerHTML属性和节点操作方法的比较,在插入大量HTML标记时使用innerHTML的效率明显要高很多。因为在设置innerHTML时,会创建一个HTML解析器。这个解析器是浏览器级别的(C++编写),因此执行JavaScript会快的多。但,创建和销毁HTML解析器也会带来性能损失。最好控制在最合理的范围内,如下:
for (var i = 0; i < 10; i ++) {
ul.innerHTML = '<li>item</li>';//避免频繁
}
//改
for (var i = 0; i < 10; i ++) {
a = '<li>item</li>';//临时保存
}
ul.innerHTML = a;