DOM文档树和节点操作
Posted luwanlin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DOM文档树和节点操作相关的知识,希望对你有一定的参考价值。
1 DOM文档树
1.1 DOM的定义(document object modle)
DOM就是文档对象模型。
/* 查看这段html代码中p的DOM模型 */
<html>
<head>
<meta charset="utf-8">
<link href="style.css">
</head>
<body>
---
<p class="mooc">
hello,<span>mooc</span>
<img src='user.jpg'>
</p>
---
<div id="div">
<h3><a href="">乔丹</a></h3>
<p>NBA<em>最伟大</em>的球员</p>
</div>
---
<div>前端微专业</div>
</body>
</html>
//在调试窗口中查看 childNodes children 对比差异
var p = document.getElementsByTagName('p');
var div = document.getElementById('div');
console.log(p);
console.log(div);
1.2 DOM API
interface Document:Node{
readonly attribute DOMImplementation implementation;
readonly attribute Element DocumentElement;
Element createElement(in DOMString tagName)
raises(DOMException);
DocumentFragment createDocumentFragment();
Text createTextNode(in DOMString data);
Comment createComment(in DOMstring date);
NodeList getElementsByTagName(in DOMString tagname);
Element getElementById(in DOMString elementID);
1.3 浏览器中的DOM
在浏览器中DOM和JS的关系:{JS[,DOM]};
1.4 DOM的内容
DOM的内容包括:DOM Core
,DOM HTML
,DOM Style
,DOM Event
1.5 DOM树
<html>
<head>
<meta charset="utf-8">
<link href="style.css">
</head>
<body>
<p class="mooc">
hello,<span>mooc</span>
<img src='user.jpg'>
</p>
<div>前端微专业</div>
</body>
</html>
上面这段代码的DOM树如下所示:
1.6 节点遍历
可用node.parentNode
,node.firstChild
,node.lastChild
,node.previousSibling
,node.nextSibiling
来遍历DOM节点;
注:节点(node)的操作,必须是node节点,不能是nodes-collection。
1.7 节点类型
DOM节点分为:element_node
,text_node
,comment_node
,document_type_node
;
在【4.1.6】和【4.1.7】的树状图中,圆型节点表示element_node
,方形节点表示text_node
.
1.8 元素遍历
如下一段HTML代码:
<p>
hello,<em>jerry!</em>
欢迎来<a href="#">China</a>。
</p>
上面HTML代码的DOM树如下所示:
//获取'hello,'和'。'
p.firstChild
p.lastChild
p.firstElementChild//<em>jerry!</em>
p.lastElementChild//<a href="#">Chia</a>
em.nextElementSibling //<a href="#">China</a>
em.previousElementSibling //null 而不是undefined!!!
2 节点操作
2.1 获取节点
- 通过元素关系获取节点
- 父子关系
parentNode
firstChild
/firstElementChild
,lastChild
/lastElementChild
childnodes
/children
- 兄弟关系
previousSibling
/nextSibling
previousElementSibling
/nextElementSibling
- 父子关系
但是,通过元素关系获取节点,可维护性很差!!!
- 通过接口获取关系
getElementById
getElementsByTagName
getElementsByClassName
querySelector/All
2.1-A getElementById
/* getElementById */
/* element = document.getElementById(id) */
---
<body>
<p id="hello" class="mooc">
hello,<span>mooc</span><img src="user.jpg">
</p>
</body>
---
//获取id为hello的p
document.getElementById("hello")//在console面板中应该得到“p#hello.mooc”的DOM对象
2.1-B getElementsByTagName
/* getElementsByTagName */
/* collection = element.getElementsByTagName(tagName) */
---
<div id="users">
<h2>8882人在学习该课程</h2>
<ul>
<li class="user">Satoshi</li>
<li class="user">春来草青</li>
<li class="user last">Kash</li>
</ul>
</div>
//切记,这里不能用p来代替div!!!
---
//先获取div#users对象,在用div#user对象来获取li对象
var users = document.getElementById("users");
//获取li
users.getElementsByTagName("li");//[li.user,li.user,li.user.last]
users.getElementsByTagName("li")[2];//li.user.last:<li class="user last">Kash</li>
//获取全部的tag
users.getElementsByTagName("*");//[h2,ul,li.user,li.user,li.user.last]
/* 注:getElementsByTagName得到的collection是动态的 */
2.1-C getElementsByClassName
/* getElementsByClassName */
/* collection = element.getElementsyClassName(className) */
---
<div id="users">
<h2>the story of Qin dynasty</h2>
<ul>
<li class="user">Qinshi moon</li>
<li class="user">tianxingjiuge</li>
<li class="user last">daqindiguo</li>
</ul>
</div>
---
//先获取div#users对象,再用div#users对象来获取li对象
var users = document.getElementById("users");
//获取li
users.getElementsByClassName("user");//[li.user,li.user,li.user.last]
users.getElementsByClassName("user")[2];//[li.user.last]
users.getElementsByClassName("user last"); !== user.getElementsByClassName("last user");//[li.user.last]
//上面两个虽然形式上看起来一样,但是前一个是一个数组的项,后一个是一个数组。
/* 兼容IE6,7,8的getElementsByClassName */
function getElementsByClassName(root,className){
//特性侦测
if(root.getElementsByClassName){
//优先使用W3C规范
return root.getElementsByClassName(className);
}else{
//获取所有的后代元素
var elements = root.getElementsByTagName("*");
var result = [];
for(var i=0,element;element=elements[i];i++){
//选择包含有类名的元素并push到新的Array
if(hasClassName(element,className)){
result.push(element);
}
}
return result;
}
}
/* getElementsByClassName得到的collection是动态的 */
2.1-D querySelector/All
/* querySelector/All */
/* list = element.querySelector/All(selector) */
---
<div id="users">
<h2>a faiary tale</h2>
<ul>
<li class="user">for child</li>
<li class="user">for adult</li>
<li class="user last">for all</li>
</ul>
</div>
---
//用querySelector获取div#users
var users = document.querySelector("#users");//div#users
//用querySelectorAll获取.user
users.querySelectorAll(".user");//[li.user,li.user,li.user.last]
document.querySelectorAll("#users .user");//[li.user,li.user,li.user.last]
/* querySelector/All得到的list是非动态的。*/
2.2 创建节点
/* createElement(tagName) */
/* element = document.createElement(tagName) */
document.creatElement("div");//<div></div>
document.creatElement("a");//<a></a>
var sc = document.createElement("script");//<script></script>
2.3 修改节点
2.3-A textContent
/* element.textContent */
---
<div class="users">
<h2>there are three boys</h2>
<ul>
<li class="user">one</li>
<li class="user">two</li>
<li class="user last">tree</li>
</ul>
</div>
---
//首先获取或者创建节点
var users = document.getElementById("users");
//读取或修改node的内容
users.textContent;//"there are three boys one two three"
users.last.textContent;//"tree"//is this right?错啦!!!
users.lastElementChild.lastElementChild.textContent;//"tree"
users.last.textcontent = "three";//is this right?错了!!!
users.lastElementChild.lastElementChild.textContent="three";//"three"
/* ie9不支持textContent */
2.3-B innerText
/* element.innerText */
//兼容firefox
if(!('innerText'in document.body)){
HTMLElement.prototype._defineGetter_("innerText",function(){
return this.textContent;
});
HTMLElement.prototype._defineSetter_("innerText",function(s){
return this.TextContent=s;
});
}
2.4 插入节点
2.4-A appendChild
/* appendChild */
/* var achild = element.appendChild(achild); */
---
<div id="users">
<h2>I can do what I want to do</h2>
<ul>
<li class="user">
<img src="4.jpg">
<a href="/user/4">lifeng</a>
</li>
</ul>
</div>
---
//完场上述HTML段落
var users = document.getElementById("users");//获得div#user节点
var h2 = document.createElement("h2");//创建h2
var ul = document.createElement("ul");//创建ul
users.appendChild(h2);//添加h2到div#users
users.appendChild(ul);//添加ul到div#users
var li = document.createElement("li");//创建li
li.className = "user";//li的className
ul.appendChild(li);//添加li到ul
var img = document.createElement("img");//创建img
img.src = "4.jpg";//设置img的src
li.appendChild(img);//添加img到li
var a = document.createElement("a");//创建a
a.href = "/user/4";//设置a的href
a.innerText = "lifeng";//设置a的innerText
li.appendChild(a);//添加a到li
2.4-B insertBefore
/* insertBefore */
element.insertBefore(achild,referenceChild);
---
<div id="users">
<h2>you need to work harder</h2>
<ul></ul>
</div>
---
//完成上述需求
var users = document.getElementById("users");//获取div#users
var h2 = document.createElement("h2");//创建h2
var ul = document.createElement("ul");//创建ul
users.appendChild(ul);//插入ul
users.insertBefore(h2,ul);//在ul前面插h2
2.5 删除节点
/* removeChild */
/* element.removeChild(child) */
var user2 = users.getElementByClassName("user2");//获取到.user2
user2.parentNode.removeChild(user2);//通过user2.parentNode来删除user2
2.6 innerHTML
/* element.innerHTML */
---
<ul id="users">
<li class="user">
<img src="4.jpg">
<a href="/user/4">yahoo</a>
</li>
</ul>
---
//用innerHTML方法在ul#users下添加元素
var users = document.getElementById("users");//获取ul#users
var li = document.createElement("li");//创建li
li.className="user";//设置li的className
users.appendChild(li);//把li.user插入ul#users中
li.innerHTML = '<img src="4.jpg"> <a href="/user/4">yahoo</a>';//用innerHTML插入li.user中的内容。
//如果要用前面的常规方法,则需要下面的一串代码:
var img = document.createElement("img");//创建img
img.src="4.jpg";//设置img的src
users.appendChild(img);//把img插入到ul#users中
var a = document.createElement("a");//创建a
a.href = "/user/4";//设置a元素的href
a.innerText = "yahoo";//设置a元素的innerText
users.appendChild(a);//把a元素插入到ul#users中
以上是关于DOM文档树和节点操作的主要内容,如果未能解决你的问题,请参考以下文章