深入理解DOM節點操作

来源:http://www.cnblogs.com/xiaohuochai/archive/2016/08/19/5787459.html
-Advertisement-
Play Games

[1]創建節點 [2]插入節點 [3]移除節點 [4]替換節點 [5]複製節點 ...


×
目錄
[1]創建節點 [2]插入節點 [3]移除節點[4]替換節點[5]複製節點

前面的話

  一般地,提起操作會想到“增刪改查”這四個字,而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'

  所有節點都有一個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>

 

替換節點

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>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 面向對象是一種編程思想,和具體語言無關.c,java,JavaScript,php都可以進行帶有自己風格的面向對象的開發. 類是對一類事物都有的屬性和行為的封裝,為什麼需要類?首先我們要想想如果沒有類會怎麼樣?如果沒有類,假設現在我們要表示一輛普通的自行車,我們會想輪子數量2個,價格多少…然後我們又 ...
  • 原文來自:http://zhengdl126.iteye.com/blog/419850 第1章 引言 隨著互聯網應用的廣泛普及,海量數據的存儲和訪問成為了系統設計的瓶頸問題。對於一個大型的 互聯網應用,每天幾十億的PV無疑對資料庫造成了相當高的負載。對於系統的穩定性和擴展性造成了極大的問題。通過數 ...
  • 本視頻為activiti工作流的web流程設計器整合視頻教程 整合Acitiviti線上流程設計器(Activiti-Modeler 5.21.0 官方流程設計器) 本視頻共講了兩種整合方式 1. 流程設計器和其它工作流項目分開部署的方式 2. 流程設計器和SSM框架項目整合在一起的方式 視頻大小 ...
  • 先從web session的共用說起 許多系統需要提供7*24小時服務,這類系統肯定需要考慮災備問題,單台伺服器如果宕機可能無法立馬恢復使用,這必定影響到服務。這個問題對於系統規模來說,從小到大可能面臨的難度會相差很大。但對於原理來說其實就是需要準備備份系統隨時可以替代正在服務的系統,也就是無論何時 ...
  • scjp test( 線上測試網站):http://scjptest.com/mock-test.xhtml 《SCJP Sun® Certified Programmer for Java™ 6 Study Guide》(Exam 310-065) PDF Java技能回答網站: 無論你遇到什麼樣... ...
  • 0.前提條件 環境兩台ubuntu版本14.04 64位系統(並獲取root許可權) 假設兩台伺服器ip為:172.16.34.214(master),172.16.34.215(backup),keepalived的虛擬ip為172.16.34.216 兩台ubuntu系統上裝好docker,版本如 ...
  • 1、框模型:盒模型,①對象實際寬度=左右外邊距+左右邊框+左右內邊距 + width;②對象實際高度=上下外邊距+上下邊框+上下內邊距 + height; 2、外邊距:margin:取值:①top(上) right(右) bottom(下) left(左);②value:一個值,四個方向相同;③to ...
  • 輪播圖在以後的應用中還是比較常見的,不需要多少行代碼就能實現。但是在只掌握了js基礎知識的情況下,怎麼來用較少的而且邏輯又簡單的方法來實現呢?下麵來分析下幾種不同的做法: 1、利用位移的方法來實現 首先,我們可以在body中添加一個div並且將寬度設置成百分比(自適應頁面),比例具體是相對誰的百分比 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...