前面的話
一般地,提起操作會想到“增刪改查”這四個字,而DOM節點操作也類似地對應于此,接下來將詳細介紹DOM的節點操作方法
前提
DOM提供節點操作的方法是因為DOM節點關系指針都是只讀的
下列代碼中想通過修改myUl的父級節點來修改其節點關系,但由于parentNode屬性是只讀的,所以修改無效,在IE8-瀏覽器下甚至會報錯
<div id="myDiv"></div> <ul id="myUl"> <li id="myli"></li> </ul> <script> console.log(myUl.parentNode);//<body> myUl.parentNode = myDiv; //標準瀏覽器下,依然返回<body>;而IE8-瀏覽器則會報錯 console.log(myUl.parentNode); </script>
DOM節點操作方法包括創建節點、插入節點、刪除節點、替換節點、查看節點和復制節點。查看節點指的是查看節點之間的關系,在節點關系部分已經做過詳細介紹,就不再贅述
創建節點
createElement()
document.createElement()方法可以創建新元素。這個方法接受一個參數,即要創建元素的標簽名,這個標簽名在HTML文檔中不區分大小寫
var oDiv = document.createElement("div"); console.log(oDiv);//<div>
IE8-瀏覽器可以為這個方法傳入完整的元素標簽,也可以包含屬性
var oDiv = document.createElement('<div id="box"></div>'); console.log(oDiv.id);//'box'
利用這種方法可以避開IE7-瀏覽器在動態創建元素的下列問題
1、不能設置動態創建的<iframe>元素的name特性
2、不能通過表單的reset()方法重設動態創建的<input>元素
3、動態創建的type特性值為"reset"的<button>元素重設不了表單
4、動態創建的一批name相同的單選按鈕彼此毫無關系。name值相同的一組單選按鈕本來應該用于表示同一選項的不同值,但動態創建的一批這種單選按鈕之間卻沒有這種關系
var iframe = document.createElement("<iframe name = 'myframe'></iframe>"); var input = document.createElement("<input type='checkbox'>); var button = document.createElement("<button type = 'reset'></button>"); var radio1 = document.createElement("<input type='radio' name ='choice' value = '1'>"); var radio2 = document.createElement("<input type='radio' name ='choice' value = '2'>");
所有節點都有一個ownerDocument的屬性,指向表示整個文檔的文檔節點document;在使用createElement()方法創建新元素的同時,也為新元素設置了ownerDocument屬性
<div id="myDiv"></div> <script> console.log(myDiv.ownerDocument);//document var newDiv = document.createElement('div'); console.log(newDiv.ownerDocument);//document console.log(newDiv.ownerDocument === myDiv.ownerDocument);//true </script>
插入節點
appendChild()
appendChild()方法用于向childNodes列表的末尾添加一個節點,并返回新增節點。添加節點后,childNodes中的新增節點、父節點和以前的最后一個子節點的關系指針都會相應地得到更新
<div id="box"></div> <script> var oBox = document.getElementById('box'); var newNode = document.createElement('ul'); var returnedNode = oBox.appendChild(newNode); console.log(returnedNode.nodeName);//UL console.log(returnedNode == newNode);//true console.log(returnedNode == oBox.lastChild);//true </script>
如果插入的節點已經是文檔的一部分了,那結果就是將該節點從原來的位置轉移到新位置
<body> <div id="oldDiv">第一個div</div> <div id="newDiv">第二個div</div> <button id="btn">變換位置</button> <script> btn.onclick = function(){ document.body.appendChild(newDiv); } </script> </body>
insertBefore()
insertBefore()方法接收兩個參數:要插入的節點和作為參照的節點。插入節點后,被插入的節點會變成參照節點的前一個兄弟節點(previousSibling),同時被方法返回。如果參照節點是null,則insertBefore()與appendChild()方法執行相同的操作。同樣地,如果插入的節點已經是文檔的一部分了,那結果就是將該節點從原來的位置轉移到新位置
referenceNode.parentNode.insertBefore(newNode,referenceNode);
<ul id="myUl" style="border:1px solid black;"> <li id="myLi"> <div id='oldDiv'>oldDiv</div> </li> </ul> <button id="btn1">插入oldDiv的前面</button> <button id="btn2">插入myUl的前面</button> <button id="btn3">插到oldDiv的里面</button> <script> var oDiv = document.createElement('div'); oDiv.innerHTML = 'newDiv'; btn1.onclick = function(){ console.log(myLi.insertBefore(oDiv,oldDiv));//<div>newDiv</div> } btn2.onclick = function(){ console.log(document.body.insertBefore(oDiv,myUl));//<div>newDiv</div> } btn3.onclick = function(){ console.log(oldDiv.insertBefore(oDiv,null));//<div>newDiv</div> } </script>
【小效果】
<ul class="list" id="list"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in">4</li> <li class="in">5</li> <li class="in">6</li> </ul> <script> var oList = document.getElementById('list'); //新增一個li元素 var oAdd = document.createElement('li'); //設置新增元素的css樣式 oAdd.className = "in"; oAdd.style.cssText = 'background-color:red;border-radius:50%'; //添加到oList中 oList.insertBefore(oAdd,null); var num = -1; var max = oList.children.length; function incrementNumber(){ num++; //oList.getElementsByTagName('li')[max]相當于null,所以不報錯 oList.insertBefore(oAdd,oList.getElementsByTagName('li')[num]); if(num == max){ num = -1; } if(num == 0){ num = 1; } setTimeout(incrementNumber,1000); } setTimeout(incrementNumber,1000); </script>
insertAfter()
由于不存在insertAfter()方法,如果要插在當前節點的某個子節點后面,可以用insertBefore()和appendChild()封裝方法
function insertAfter(newElement,targetElement){ var parent = targetElement.parentNode; if(parent.lastChild == targetElement){ parent.appendChild(newElement); }else{ parent.insertBefore(newElement,targetElement.nextSibling) } }
<div id='oldDiv'>old</div> <button id="btn">增加節點</button> <script> function insertAfter(newElement,targetElement){ var parent = targetElement.parentNode; if(parent.lastChild == targetElement){ return parent.appendChild(newElement); }else{ return parent.insertBefore(newElement,targetElement.nextSibling) } } var newDiv = document.createElement('div'); newDiv.innerHTML = 'new'; btn.onclick = function(){ insertAfter(newDiv,oldDiv); } </script>
insertAdjacentHTML()
insertAdjacentHTML()方法作為終級辦法,相當于前面三個方法的綜合。該方法接收兩個參數:插入的位置和要插入的HTML文本
第一個參數必須是下列值之一,且這些值都必須是小寫形式:
"beforebegin" 在當前元素之前插入一個緊鄰的同級元素 "afterbegin" 在當前元素之下插入一個新的子元素或在第一個子元素之前再插入新的子元素 "beforeend" 在當前元素之下插入一個新的子元素或在最后一個子元素之后再插入新的子元素 "afterend" 在當前元素之后插入一個緊鄰的同級元素
第二個參數是一個HTML字符串,如果瀏覽器無法解析字符串,就會拋出錯誤
[注意]該方法無返回值
<div id='target' style="border: 1px solid black;">This is the element content</div> <button>beforebegin</button> <button>afterbegin</button> <button>beforeend</button> <button>afterend</button> <script> var btns = document.getElementsByTagName('button'); for(var i = 0 ; i < 4; i++){ btns[i].onclick = function(){ var that = this; target.insertAdjacentHTML(that.innerHTML,'<span id="test">測試</span>') } } </script>
移除節點
removeChild()
removeChild()方法接收一個參數,即要移除的節點,被移除的節點成為方法的返回值
<div id="myDiv">等待移除的節點</div> <button id="btn">移除節點</button> <script> btn.onclick = function(){ document.body.removeChild(myDiv); } </script>
下面代碼可以移除當前節點的所有子節點
var element = document.getElementById("top"); while (element.firstChild) { element.removeChild(element.firstChild); }
【小效果】
<button id="btn">開始刪除節點</button> <ul class="list" id="list"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in">4</li> <li class="in">5</li> <li class="in">6</li> </ul> <script> var oList = document.getElementById('list'); function incrementNumber(){ //獲取oList中子元素的個數 var len = oList.getElementsByTagName('li').length; //如果長度不為0 if(len){ //刪除最后一個子元素 oList.removeChild(oList.getElementsByTagName('li')[len-1]); //再次調用計時器 setTimeout(incrementNumber,1000); } } btn.onclick = function(){ //1s后執行函數incrementNumber setTimeout(incrementNumber,1000); } </script>
remove()
相比于removeChild(),remove()方法不太常見,但是卻非常簡單。該方法不用調用其父節點,直接在當前節點使用remove()方法就可以刪除該節點,無返回值
remove()方法常用于刪除元素節點和文本節點,不可用于特性節點
[注意]IE瀏覽器不支持該方法
<div id="test" title='div'>123</div> <script> //文本節點 console.log(test.childNodes[0]);//'123' test.childNodes[0].remove(); console.log(test.childNodes[0]);//undefined //特性節點 console.log(test.attributes.title);//'div' //報錯,remove()方法無法用于刪除特性節點 try{test.attributes[0].remove()}catch(e){ console.log('error'); } //元素節點 console.log(test); test.remove(); </script>
替換節點
replaceChild()
replaceChild()接收的兩個參數是要插入的節點和要替換的節點,要替換的節點將由這個方法返回并從文檔樹中移除,同時由要插入的節點占據其位置
oldChild.parentNode.replaceChild(newChild, oldChild);
<div id="div1">1</div> <div id="div2">2</div> <div id="div3">3</div> <button id="btn1">新增節點替換(4替換2)</button> <button id="btn2">原有節點替換(3替換1)</button> <script> btn2.onclick = function(){ document.body.replaceChild(div3,div1); } btn1.onclick = function(){ var div4 = document.createElement('div'); div4.innerHTML = '4'; document.body.replaceChild(div4,div2); } </script>
【小效果】
<button id="btn">開始替換節點</button> <ul class="list" id="list"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in">4</li> <li class="in">5</li> <li class="in">6</li> </ul> <script> var oList = document.getElementById('list'); //新增一個li元素 var oAdd = document.createElement('li'); //設置新增元素的css樣式 oAdd.className = "in"; oAdd.style.cssText = 'background-color:red;border-radius:50%'; btn.onclick = function(){ //1s后oAdd替換第0個li setTimeout(function(){ oList.replaceChild(oAdd,document.getElementsByTagName('li')[0]); //1s后執行incrementNumber函數 setTimeout(incrementNumber,1000); },1000); } function incrementNumber(){ //獲取oList中第1個li var oLi1 = document.getElementsByTagName('li')[1]; //若存在則進行替換處理 if(oLi1){ oList.replaceChild(oAdd,oLi1); setTimeout(incrementNumber,1000); } } </script>
復制節點
cloneNode()
cloneNode方法用于克隆一個節點。它接受一個布爾值作為參數,表示是否執行深復制。在參數為true時,執行深復制,也就是復制節點及整個子節點樹。在參數為false的情況下,執行淺復制,即復制節點本身。復制后返回的節點副本屬于文檔所有,但并沒有為它指定父節點。若參數為空,也相當于false
[注意]cloneNode()方法不會復制添加到DOM節點中的javascript屬性,例如事件處理程序等。這個方法只復制特性和子節點,其他一切都不會復制
<ul id="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> <script> var oList = document.getElementById('list'); oList.index = 0; var deepList = oList.cloneNode(true); //成功復制了子節點 console.log(deepList.children.length);//6 //但并沒有復制屬性 console.log(deepList.index);//undefined var shallowList = oList.cloneNode(); //淺復制不復制子節點 console.log(shallowList.children.length);//0 </script>
文章列表