首頁 > web前端 > js教程 > 主體

JavaScript中對DOM節點的存取、建立、修改、刪除_基礎知識

WBOY
發布: 2016-05-16 15:32:11
原創
1572 人瀏覽過

DOM
DOM就是Document object Model的縮寫。文檔物件模型是把XML或HTML以樹節點為表現形式的文檔。用DOM方法和屬性,你可以訪問,修改,刪除頁面上任意一個元素,也是可以新增一個元素。 DOM是獨立於語言的API,可以被任意語言實現,當然也包括了Javascript
看看下面的一個文字。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
 <head> 
  <title>My page</title> 
 </head> 
 <body> 
  <p class="opener">first paragraph</p> 
  <p><em>second</em> paragraph</p> 
  <p id="closer">final</p> 
 </body> 
</html> 
登入後複製

 
我們來看看第二段

<p><em>second</em> paragraph</p> 

登入後複製

可以看到這是p標籤。它被包含在body標籤中。所以說body是p的父節點,p是子節點。第一段和第三段也是body的子節點。它們都是第二段的兄弟節點。這個em標籤是第二段p的子節點。因此p就是它的父節點。父子節點關係能描繪出像樹一樣的關係。所以叫做DOM結構樹(DOM tree).
 
Core DOM 和 HTML DOM
我們已經知道DOM可以描繪出HTML和XML文件。事實上HTML文檔就是XML文檔,只不過更規範些。因此作為DOM Level 1的一部分,Core DOM規範適用於所有XML文檔以及HTML DOM規範擴展了Core DOM.當然HTML DOM不能適用於所有的XML文檔,僅適用於HTML文檔。讓我們來看看Core DOM和HTML DOM的構造器。
 
構造器關係

20151116142938841.png (639×572)

訪問DOM節點
當要驗證表單或更換圖片之前,我們要知道怎麼樣存取元素(element.)。有很多方法獲取元素。
 
Document節點
透過document我們可以存取目前的文件。我們可以透過firebugs(火狐插件),來查看document的屬性和方法。
 
所有的節點都有nodeType,nodeName,nodeValue的屬性。我們來看看document的nodeType是什麼

document.nodeType;//9 
登入後複製

 一共有12節點類型。 document是9。常用的是元素(element:1),屬性(attribute:2),文本(text:3)。
節點還有名稱。對於HTML標籤。節點名稱就是標籤名稱。文字節點(text)的名字是#text.文檔節點(document)的名字是#document.
 
節點也有值。對於文字節點,值就是文字。 document的值為null
 
documentElement
XML都會有個ROOT節點來包裝文件包含起來。對於HTML文件。 ROOT節點就是html標籤。訪問root節點。可以用documentElement的屬性。

document.documentElement;//<html> 
document.documentElement.nodeType;//1 
document.documentElement.nodeName;//HTML 
document.documentElement.tagName;//对于element,nodeName和tagName相同 
登入後複製

 
 Child Nodes
為了確定是否包含子節點我們可以用以下方法

document.documentElement.hasChildNodes();//true 
登入後複製

 HTML有兩個子節點。

document.documentElement.childNodes.length;//2 
 
document.documentElement.childNodes[0];//<head> 
 
document.documentElement.childNodes[1];//<body> 
登入後複製

  也可以透過子節點存取父節點

document.documentElement.childNodes[1].parentNode;//<html> 
登入後複製

 我們把body的引用賦值變數

var bd = document.documentElement.childNodes[1]; 
bd.childNodes.length;//9 
登入後複製

 讓我們來看看body的結構

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body>
登入後複製

  
 為什麼子節點個數為9個呢。
 首先是4個P還有一個註釋一共4個。
 4個節點包含了3個空白的節點。這就7個。
 第8個在body和第一個p之間的空白節點。
 第9個就是在註解與之間的空白節點。
 共9個節點。
 
屬性
因為第一節點是空白節點,所以第二個節點才是第一個p標籤。

bd.childNodes[1];//  <p class="opener"> 
登入後複製

可以查看它是否有屬性

bd.childNodes[1].hasAttributes();//true 
登入後複製

也可以看attributes的數量

bd.childNodes[1].attributes.length;//1 
 
//可以用index和名字来访问属性,也可以用getAttribute方法。 
bd.childNodes[1].attributes[0].nodeName;//class 
 
bd.childNodes[1].attributes[0].nodeValue;//opener 
 
bd.childNodes[1].attributes['class'].nodeValue;//opener 
 
bd.childNodes[1].getAttribute('class');//opener 
登入後複製

 訪問標籤裡的內容
讓我們來看看第一個標籤p
你可以用textContent屬性來存取。要注意的是,在IE瀏覽器中並不存在textContent,請用innerText來替換,結果都是一樣的。

bg.childNodes[1].textContent;// "first paragraph" 
登入後複製

還有一個屬性是innerHTML.這並不是DOM的規範。但是主流瀏覽器都支援這個屬性。它回傳的是HTML程式碼。
 

bg.childNodes[1].innerHTML;// "first paragraph" 
登入後複製

第一段沒有html程式碼,所以結果跟textContent(IE裡是innerText)是一樣的。來看下第二段包含HTML程式碼的標籤

bd.childNodes[3].innerHTML;//"<em>second</em> paragraph" 
 
bd.childNodes[3].textContent;//second paragraph 
登入後複製

 
另一種方法可以取得文字節點,然後再取nodeValue屬性,程式碼如下

bd.childNodes[1].childNodes.length;//1 子节点个数 
 
bd.childNodes[1].childNodes[0].nodeName;// 节点名称 #text 
 
bd.childNodes[1].childNodes[0].nodeValue;//节点值 first paragraph 
登入後複製


快速访问DOM
通过childNodes,parentNode,nodeName,nodeValue以及attributes,可以访问文档任意的节点了。但是在实际运用过程中,文本节点是比较讨厌的。如果文本改变了,有可能就影响脚本了。还有如果DOM树足够的深入,那么访问起来的确有些不方便。幸好我们可以用更为方便的方法来访问节点。这些方法是

getElementsByTagName()
getElementsByName()
getElementById()
登入後複製

首先说下getElementsByTagName()
通过一个标签名称(tag name)来获取一个html元素的集合。例子如下

document.getElementsByTagName('p').length;//3 
登入後複製

因为返回的是个集合,我们可以用过数组下标的形式来访问或者通过item方法。比较一下还是推荐用数组的访问方法。更简单一些。

document.getElementsByTagName('p')[0];// <p class="opener"> 
document.getElementsByTagName('p').item(0);//和上面的结果一样 
 
document.getElementsByTagName('p')[0].innerHTML;//first paragraph 
登入後複製


访问元素的属性,可以用attributes集合。但是更简单的方法是直接作为一个属性来访问就行。看个例子

document.getElementsByTagName('p')[2].id;//closer 
登入後複製

要注意的是,class属性不能正常的使用。。要用className。因为class在javascript规范中是保留字。

document.getElementsByTagName('p')[0].className;//opener 
登入後複製

我们可以用如下方法访问页面所有元素

<span style="color: #ff0000;">document.getElementsByTagName('*').length;//9</span> 
登入後複製

注意:在IE早期的版本不支持上述方法。可以用document.all来取代。IE7已经支持了,但是返回的是所有节点(node),而不仅仅是元素节点(element nodes)。


Siblings, Body, First, Last Child
nextSibling和previousSibling是两个比较方便访问DOM的方法。用来访问相邻的节点的。例子如下

var para = document.getElementById('closer') 
para.nextSibling;//"\n" 
para.previousSibling;//"\n" 
para.previousSibling.previousSibling;//<p> 
para.previousSibling.previousSibling.previousSibling;//"\n" 
para.previousSibling.previousSibling.nextSibling.nextSibling;// <p id="closer"> 
登入後複製


body 用来访问body元素的。

document.body;//<body> 
登入後複製

firstChild 和lastChild 。firstChild是和childNodes[0]一样.lastChild和 childNodes[childNodes.length - 1]一样。

遍历DOM
通过以上的学习,我们可以写个函数,用来遍历DOM

function walkDOM(n) { 
 do { 
  alert(n); 
  if (n.hasChildNodes()) { 
   walkDOM(n.firstChild) 
  }   
 } while (n = n.nextSibling) 
} 
 
walkDOM(document.body);//测试 

登入後複製

修改节点
下面来看看DOM节点的修改。
先获取要改变的节点。

var my = document.getElementById('closer'); 
登入後複製

非常容易更改这个元素的属性。我们可以更改innerHTML.

my.innerHTML = 'final';//final 
登入後複製

因为innerHTML可以写入html,所以我们来修改html。

my.innerHTML = '<em>my</em> final';//<em>my</em> fnal 
登入後複製

em标签已经成为dom树的一部分了。我们可以测试一下

my.firstChild;//<em> 
my.firstChild.firstChild;//my 
登入後複製

我们也可以通过nodeValue来改变值。

my.firstChild.firstChild.nodeValue = 'your';//your 
登入後複製


修改样式
大部分修改节点可能都是修改样式。元素节点有style属性用来修改样式。style的属性和css属性是一一对应的。如下代码

my.style.border = "1px solid red"; 
登入後複製

CSS属性很多都有破折号("-"),如padding-top,这在javascript中是不合法的。这样的话一定要省略波折号并把第二个词的开头字母大写,规范如下。 margin-left变为marginLeft。依此类推

my.style.fontWeight = 'bold'; 
登入後複製

我们还可以修改其他的属性,无论这些属性是否被初始化。

my.align = "right"; 
my.name = 'myname'; 
my.id = 'further'; 
my;//<p id="further" align="right" style="border: 1px solid red; font-weight: bold;"> 
登入後複製


创建节点

为了创建一个新的节点,可以使用createElement和createTextNode.如果新建完成,可以用appendChild()把节点添加到DOM树中。
创建一个元素P,并把设置innerHTML属性

var myp = document.createElement('p'); 
myp.innerHTML = 'yet another'; 
登入後複製


元素P建完成了,就可以随意修改添加属性了

myp.style.border = '2px dotted blue' 
登入後複製

接下来可以用appendChild把新的节点添加到DOM树中的。

document.body.appendChild(myp) 
登入後複製


使用DOM的方法
用innerHTML方法的确很简单,我们可以用纯的dom方法来实现上面的功能。

  • 新建一个文本节点(yet another)
  • 新建一个段落
  • 把文本节点添加到段落中。
  • 把段落添加到body中
// 创建p 
var myp = document.createElement('p'); 
// 创建一个文本节点 
var myt = document.createTextNode('one more paragraph') 
myp.appendChild(myt); 
// 创建一个STRONG元素 
var str = document.createElement('strong'); 
str.appendChild(document.createTextNode('bold')); 
// 把STRONG元素添加到P中 
myp.appendChild(str); 
// 把P元素添加到BODY中 
document.body.appendChild(myp); 
//结果<p>one more paragraph<strong>bold</strong></p> 
 cloneNode()
登入後複製

另一种新建节点的方法是,我们可以用cloneNode来复制一个节点。cloneNode()可以传入一个boolean参数。如果为true就是深度复制,包括他的子节点,false,仅仅复制自己。

首先获取要复制的元素。

var el = document.getElementsByTagName('p')[1];//<p><em>second</em> paragraph</p> 
登入後複製

先不用深度复制。

document.body.appendChild(el.cloneNode(false)) 
登入後複製

我们发现页面并没有变化,因为仅仅复制的是元素p。和下面的效果一样。

document.body.appendChild(document.createElement('p')); 
登入後複製

如果用深度复制,包括p下面所有的子节点都会被复制。当然包括文本节点和EM元素。

document.body.appendChild(el.cloneNode(true)) 
登入後複製


insertBefore()
用appendChild,就是把元素添加到最后。而insertBefore方法可以更精确控制插入元素的位置。

elementNode.insertBefore(new_node,existing_node) 
登入後複製

实例

document.body.insertBefore( 
 document.createTextNode('boo!'), 
 document.body.firstChild 
); 
登入後複製


意思就是新建一个文本节点,把它作为body元素的第一个节点。


删除节点

要从DOM树删除一个节点,我们可以使用removeChild().我们来看看要操作的HTML

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body> 
登入後複製

来看看下面代码,删除第二段

var myp = document.getElementsByTagName('p')[1]; 
var removed = document.body.removeChild(myp); 
登入後複製

removed节点就是删除的节点。以后还可以用这删除的节点。

我们也可以用replaceChild()方法。这个方法是删除一个节点,并用另一个节点替代。当执行上个删除节点操作之后,结果如下

<body> 
 <p class="opener">first paragraph</p> 
 <p id="closer">final</p> 
 <!-- and that's about it --> 
</body> 
登入後複製

我们来看看replaceChild的使用。我们把上一个删除节点来替代第二个p

var replaced = document.body.replaceChild(removed, p); 
登入後複製

和removeChild返回一样。replaced就是移除的节点。现在结果为

<body> 
 <p class="opener">first paragraph</p> 
 <p><em>second</em> paragraph</p> 
 <!-- and that's about it --> 
</body> 
登入後複製

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!