[Javascript]:DOM概念、DOM操作元素、屬性、文本節點詳解

【篇幅略長,建議點擊上面目錄來快速查詢相關知識點】

首先簡單瞭解一下Javascript的三大組成部分:ECMAScript + BOM + DOM。

  • ECMAScript是JS的語言核心。
  • BOM和DOM是中立於平臺和語言的應用程序接口(API),不和任何語言進行綁定,Javascript只是對其進行實現。
  • 我們可以通過JS的BOM對象對瀏覽器的功能部件進行訪問,相關知識點擊BOM知識。通過DOM對象來操作文檔內容。

DOM概念

         DOM全稱是文檔對象模型,是專門用於操作HTML/XML文檔的API(應用程序接口)。DOM將文檔看作一顆樹,其中的每個成分都是對象,這些對象都看作是節點。可以將文檔的一切都理解成節點對象。

        DOM的組成部分介紹:文檔、對象和模型

  • Document(文檔):當用瀏覽器打開一個頁面文檔時,這個文檔就會被轉成document對象,然後就可以調用了。後面會提到該對象的用法。
  • Object(對象):DOM中的每個節點都是對象,通過對象的屬性和方法就能夠操作節點。
  • Model(模型):DOM將整個文檔劃分成節點樹結構,如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>標題</title>
</head>
<body>
    <p>文本P</p>
    <ol>
        <li>文本1</li>
        <li>文本2</li>
    </ol>
</body>
</html>

     

DOM節點知識

DOM把文檔描述成層次節點樹,一個由多層節點組成的結構。文檔中的每個元素都是節點對象,節點可以分爲以下幾類:

  • 整個文檔是一個文檔節點,即根節點;
  • 所有的HTML標籤都是元素節點;
  • 所有的HTML 屬性都是屬性節點;
  • 包含在HTML元素中的文本內容都是文本節點;
  • 註釋節點。
注意:DOM中的根節點和根元素節點是兩回事。根節點代表整個文檔,document對象是它的唯一實例。可以把根節點理解成document對象。而根元素節點代表文檔的根元素,即<HTML>元素,可以通過document.documentElement拿到根元素節點<html>。

節點對象使用細節

  • DOM節點都是Node類型,因此所有節點對象都具有相同的屬性和方法。使用時最好根據當前節點類型來選擇適當的方法,不然會出錯。
  • 例如:一個屬性節點.appendChild(),雖然允許調用該方法,但很明顯這是不符合規定的,所以不能瞎用。
  • document對象繼承了Node對象的所有屬性和方法,在document對象中訪問某些節點屬性和方法時,因爲是根節點,這些屬性和方法是沒有意義的。如下:
document.attributes 文檔作爲根節點,沒有屬性。
document.hasAttributes() 文檔沒有該屬性
document.nextSibling 文檔沒有下一節點
document.nodeName 這個通常是 #document
document.nodeType 這個通常是 9(DOCUMENT_NODE)
document.nodeValue 文檔沒有一個節點值
document.ownerDocument 文檔沒有主文檔
document.ownerElement 文檔沒有自己的節點
document.parentNode 文檔沒有父節點
document.previousSibling 文檔沒有兄弟節點
document.textContent 文檔沒有文本節點

DOM操作節點介紹

  • DOM編程本質上就是對節點對象進行操作。
  • Javascript使用document對象來操作DOM節點,主要包括:獲取節點、操作元素節點、操作屬性節點和操作文本節點。
  • 通過操作節點就能改變文檔中的所有 HTML 元素、HTML 屬性、CSS 樣式以及對事件做出反應,讓HTML實現動態效果。

【提示:document對象是window對象的子對象之一,屬於BOM的一部分,可以通過window.document來訪問,但window前綴通常可以省略】


首先了解一下document對象的一些常用屬性,非常有用。

document對象常用屬性 

這些屬性返回的是單一對象。這些都是最初始的DOM屬性,在DOM3中又添加了許多屬性和集合屬性,如果想了解可以去搜索DOM3。
document對象屬性 描述

body

返回<body>元素。
cookie 設置或返回與當前文檔有關的所有 cookie。
domain 返回當前文檔的域名。
lastModified 返回文檔被最後修改的日期和時間。
referrer 返回載入當前文檔的文檔的 URL。
title 返回當前文檔的標題。
URL 返回當前文檔的 URL。
      var body = document.body; //拿到body元素節點
       document.writeln("URL:" + document.URL + "<br>"); //獲取當前頁面URL地址
       document.writeln("標題:" + document.title + "<br>"); //獲取當前頁面的標題
       document.writeln("域名:" + document.domain + "<br>"); //使用服務器才能看到域名,本地文件打開是沒用的。


集合屬性會返回一個包含多個屬性的數組。返回值和getElementsByTagName、getElementsByClassName方法差不多。
document對象集合屬性 描述

all[]

提供對文檔中所有 HTML 元素的訪問。
anchors[] 返回文檔中具有name屬性的<a>元素對象的集合。表示錨點。
forms[] 返回文檔中<form>元素對象的集合。
images[] 返回文檔中<image>元素對象的集合。
links[] 返回文檔中具有href屬性的<area>和<a>元素對象的集合。
<form action="" method="get" name="fuck"></form>
    <form action="" method="get"></form>
    <form action="" method="get"></form>
    <a href="" name="a1">1</a>
    <a href="" >2</a>
    <a href="" name="a3">3</a><br>
    <script>
         document.writeln("表單集合:" + document.forms + "<br>"); 
         document.writeln("表單數量:" + document.forms.length + "<br>"); 
         document.writeln("第4個表單:" + document.forms[3] + "<br>"); //undefined
         document.writeln("錨點a標籤集合:" + document.anchors + "<br>"); 
         document.writeln("錨點a標籤數量:" + document.anchors.length + "<br>"); 
    </script>

上面實例中,直接調用集合屬性就能拿到指定的元素集合,非常方便。除了之外,還能用操作節點的方式來實現這種效果:

<a href="" name="m1">a1</a>
    <a href="" >a2</a>
    <a href="" name="m3">a3</a>
    <input type="text" id="in" name="username" value="用戶">
    <script>
        var aAnchor = document.anchors;
        var rs = document.getElementsByTagName("a"); //拿到所有a標籤元素
        var count = 0; //記錄數量
        for(var i = 0; i < rs.length; i++){          
            if(rs[i].hasAttribute("name")){ //判斷有沒有name屬性
                console.log(rs[i]);
                count++;
            }
        }
        console.log("錨點鏈接數量:" + count);
    </script>


 //封裝成方法,根據標籤名和屬性名返回指定的元素數組
        function getElement(tag, nameAttr){
            //判斷參數類型
            if( (typeof tag !== 'string') || (typeof nameAttr !== 'string') ){
                alert("參數必須爲字符串!");
                return;
            }
            var eleNode = document.getElementsByTagName(tag); //通過標籤找到所有指定的元素節點
            var rs = [];//空數組
            for(var i = 0; i < eleNode.length; i++){
                if(eleNode[i].hasAttribute(nameAttr)){ //元素節點有指定屬性,則動態添加到數組
                    rs.push(eleNode[i]); 
                }
            }
            return rs;
        }

【我的這個方法是返回數組類型,而通過集合屬性返回的是HTMLCollection類型。沒搞懂這兩者有什麼實際區別】

【上面列出的屬性中,節點對象屬性按道理也可以列在其中,但因爲節點對象屬性更多的是用於節點對象,document對象使用這些節點屬性沒多大意義。所以在後面操作節點時再給上節點對象的常用屬性】

簡單介紹完document對象屬性後,下面進入DOM操作的主題。


DOM獲取元素節點

getElementById() 通過元素ID屬性值選取節點。返回單一對象
getElementsByClassName() 通過元素class屬性值選取節點。返回包含該對象的集合
getElementsByName()  通過元素name屬性值選取節點。返回包含該對象的集合
getElementsByTagName()
通過標籤名選取指定元素節點。返回包含該對象的集合

【還有一個getElementsByTagNameNS(),該方法是用於XML文檔的,知道有這麼個方法就行】

獲取元素節點實例

  <div id="div_1">
        DIV文本內容ABC
        <input type="radio" name="testName" value="1"/>天
        <input type="radio" name="testName" value="2"/>地
        <input type="radio" name="testName" value="3"/>人
        <p class="testClass">P元素中的文本</p>
        <button>按鈕</button>
        <ul>
            <li class="testClass">列表1</li>
            <li class="testClass">列表2</li>
        </ul>
        DIV最後一段文本內容
    </div>
    <script>
        //獲取id = "p_1" 的元素節點, 並拿到內部文本節點  
       var id_div_1 = document.getElementById("div_1");  
       console.log("div_1 的元素節點中的文本內容:"  +  id_div_1.innerText);  
       console.log("===============分割線=================");
       //獲取class = "testClass" 的元素節點集合  
       var classTest = document.getElementsByClassName("testClass"); 
       //遍歷元素節點集合,拿到它們的元素標籤名。  
       for(var i = 0; i < classTest.length; i++){  
           console.log("標籤名:" + classTest[i].tagName);  
       }  
       console.log("===============分割線=================");
       //獲取name = "testName"的元素節點
       var nameTest = document.getElementsByName("testName");  
       //循環獲取這些節點上value屬性的值
       for(var i = 0; i < nameTest.length; i++){  
           console.log(nameTest[i].value);  
       }  
       console.log("===============分割線================="); 
       //拿到所有input標籤的元素節點集合 
       var tagTest = document.getElementsByTagName("input");  
       for(var i = 0; i < tagTest.length; i++){  
           console.log(tagTest[i].name); //得到它們的name屬性值 
       }  
    </script>     
<!-- 執行結果請複製到文檔中,然後用瀏覽器按F12查看 -->
  • 使用建議:如果獲取的元素節點是唯一的,最好通過ID方式來獲取,直接返回單一元素對象。而其他三種都是返回元素集合,就算只獲取到一個元素,也要用指定下標獲取元素對象,所以在一次性獲取多個符合要求的元素節點時,使用getElementsXxx()系列方法會更方便。
  • 其中通過name屬性值的獲取元素節點集合方法一般用於表單元素中。


DOM獲取層次節點

獲取指定元素節點之後,通過以下的節點屬性可以很方便地獲取與它相關的層次節點,層次節點包括:父節點、子節點、兄弟節點(相鄰節點)。

DOM層次節點常用屬性 功能描述

element.nodeName

元素節點返回元素標籤,屬性節點返回屬性名稱,文本節點永遠返回#text
element.nodeType 返回元素節點類型。元素1屬性2文本3註釋8文檔9
element.nodeValue 設置或返回節點值。屬性節點返回屬性值,文本節點返回文本。文檔節點和元素節點不可用。

element.childNodes

返回當前元素的所有子節點
element.firstChild 返回當前元素的第一個子節點
element.lastChild 返回當前元素的最後一個子節點

element.parentNode

返回當前元素節點的父節點
element.previousSibling 獲取當前元素節點的前一個同級節點
element.nextSibling 獲取當前元素節點的後一個同級節點
element.attributes   獲取當前元素階段的所有屬性節點集合
element.ownerDocumen 獲取該節點的文檔根節點,即document對象
nodelist.item()  返回 NodeList 中位於指定下標的節點。
element.style    獲取當前元素節點的style屬性,即內聯樣式。

element.id /

element.className

設置或返回元素節點的id屬性。

設置或返回元素節點的class屬性。

element.innerText 

element.innerHTML

設置或返回元素節點中的所有文本內容 

設置或返回元素節點的所有HTML代碼


nodeName、nodeType和nodeValue實例
<div id="div_1">
       我是DIV中的文本內容。
       <p>P元素文本</p>
       <ul>
            <li>列表1</li>
            <li>列表2</li>
        </ul>
        <input type="text" value="NIUBI" id="in_1"/>
   </div>
   <script>
       /* nodeName、nodeType、nodeValue的作用 */
       var idDiv_1 = document.getElementById("div_1"); //獲取id div_1 的元素節點
       console.log("元素名稱:" + idDiv_1.nodeName); //獲取元素節點標籤
       console.log("元素類型:" + idDiv_1.nodeType); //元素類型:1
       console.log("根節點document對象的nodeName,nodeype,nodeValue:" + document.nodeName 
                    +","+  document.nodeName +"," + document.nodeName);
       
       var idIn_1 = document.getElementById("in_1");
       //獲取idIn_1元素節點的第一個屬性節點
       var attr = idIn_1.attributes[0];
       console.log("屬性節點名稱:" + attr.nodeName + ",屬性值:" + attr.nodeValue


獲取層次節點實例

<div id="div_1">
       <p>P元素文本</p>
       <ul>
            <li>列表1</li>
            <li>列表2</li>
       </ul>
        <input type="text" value="NIUBI" id="in_1"/>
        <button>按鈕</button>
   </div>
   <script>
        /* 以上面代碼的<div>元素來測試 */
        var idDiv_1 = document.getElementById("div_1"); //獲取id div_1 的元素節點
        console.log("父節點");
        console.log(idDiv_1.parentNode);
        console.log("所有子節點(包括空白文本節點)");
        console.log(idDiv_1.childNodes); //拿到所有子節點,包括空白文本節點

        console.log("div_1元素節點的第一個子節點和最後一個子節點")    
        console.log(idDiv_1.firstChild); //會拿到空白文本節點
        console.log(idDiv_1.lastChild); 

        console.log("忽略空白文本節點,元素子節點和最後一個元素子節點")    
        console.log(idDiv_1.firstElementChild); //第一個子節點
        console.log(idDiv_1.lastElementChild); //最後一個子節點

        var div_1s = document.getElementById("div_1"); //獲取id = div_1的元素節點
        var ul_1 = div_1s.getElementsByTagName("ul")[0]; //獲取div_1s節點中的第一個ul元素子節點
        console.log("ul元素節點的前一個節點和後一個節點");
        console.log(ul_1.previousElementSibling);    
        console.log(ul_1.nextElementSibling);

層次節點使用細節

       因爲空白文本節點的原因,所以在使用一些獲取層次節點的屬性時,要注意避免獲取到空白文本節點的問題。例如原生childNodes屬性會拿到所有子節點,包括沒多大意義的空白文本節點。但還有一個非原生屬性children,它可以獲取元素的所有的元素子節點,但會忽略一切文本節點(包括空白文本和非空白文本)。用的時候要區別開兩者。

      還有使用獲取兄弟節點、第一個和最後一個子節點的屬性時,會有兩種屬性:一種是帶Element標識,例如firstElementChild、previousElementSibing等,一種不帶Element標識,例如firstChild。它們兩者的區別就是:帶Element標識和children屬性一樣,會忽略文本節點,只認元素節點。而不帶Element標識的不會忽略空白節點和文本節點。

關於空白文本節點的問題,放在下面的操作文本節點知識中。


上面實例介紹了層次節點屬性的使用,至於節點的其他屬性和方法可以隨便點擊一下這些屬性,就能通過鏈接去w3c官網查看完整屬性和方法了。


DOM節點實現增刪改查

  • 查詢節點上面已提到。獲取元素節點後,可以通過節點對象的以下方法對文檔結構進行增刪改外加複製。

創建節點 功能描述

createElement("元素標籤") 

創建一個元素節點。
createTextNode("文本內容") 創建文本節點。
createAttribute("屬性名") 創建屬性節點(不常用)。使用setAttribute()更方便。
添加節點 功能描述

appendChild(element)

向節點的子節點列表末尾添加新的子節點
insertBefore(添加的元素節點,已知子節點) 在已知子節點前插入一個新的子節點
刪除節點 功能描述

removeChild(elementNode)

removeAttribute(attributeNode)

刪除指定的元素節點
刪除指定的屬性節點
替換節點 功能描述

replaceChild(newElement, oldElement)

新節點替換老節點,新節點會消失。注意兩者節點類型要一致。
複製節點 功能描述

nodeObject.cloneNode(boolean)

true克隆當前節點以及所有子節點;false只克隆當前節點。
包含所有節點操作方式的綜合實例,有點長,建議複製到編輯器中查看。
 <button id="btn_1">body元素中常規插入P元素</button>
    <button id="btn_2">P元素節點插入到第一個</button>
    <button id="btn_3">點擊我更換按鈕文本</button><br>
    <button id="btn_4" onclick="deleteFirstChild()">刪除body元素中的第一個子節點</button>
    <button  onclick="repalceText('div_2')">替換文本節點</button>
    <button  onclick="repalceFirstNode('div_2')">替換第一個子節點</button>
    <button  onclick="closeBtn()">克隆前三個按鈕到div_2中</button>
    <div id="div_1">
        第一個div
    </div>
    <div id="div_2">
        第二個div
    </div>
    <script>
        //添加P元素到body元素節點中,默認爲子節點尾部。
        document.getElementById("btn_1").onclick = function(){
            var creP = document.createElement("p");
            creP.innerText = "--創建的P元素節點--"; 
            document.body.appendChild(creP);
        }
        //創建一個p元素節點,並插入到body元素的第一個子節點
        document.getElementById("btn_2").onclick = function(){
            var creP = document.createElement("p"); 
            creP.innerText = "--插入到第一位的P元素節點--";
            //拿到body元素的第一個元素節點,將p元素放在它之前
            document.body.insertBefore(creP, document.body.firstElementChild); 
        } 
        //創建文本節點並插入到調用該函數的元素節點中
        document.getElementById("btn_3").onclick = function(){
            var creText = document.createTextNode("創建的文本節點");
            this.appendChild(creText);
        }
        //刪除body元素中第一個子節點   
        function deleteFirstChild(){
            var bodys = document.body;
            bodys.removeChild(bodys.firstChild);
        }
        //把body元素節點第一個子節點替換成指定元素節點的第一個子節點
        function repalceFirstNode(id){
            var firstChild = document.body.firstElementChild;
            var idTest = document.getElementById(id);
            idTest.replaceChild(firstChild, idTest.childNodes[0]);
        }
        //把body元素節點的第一個子節點的文本內容替換成指定元素節點的第一個文本節點
        function repalceText(id){
            var firstText = document.body.firstElementChild.innerText; //拿到body元素中的第一個子節點的文本內容
            var creText = document.createTextNode(firstText);//創建文本節點
            var idTest = document.getElementById(id);
            idTest.replaceChild(creText, idTest.childNodes[0]);//新文本節點替換成獲取指定元素節點的第一個子節點(可能是空白文本)
        }
        //克隆前三個按鈕元素節點
        function closeBtn(){
           var buttons = document.getElementsByTagName("button");
           for(var i = 0; i < 3; i++){
               document.getElementById("div_2").appendChild(buttons[i].cloneNode(true)); //深度克隆,包含所有子節點
           }
        }
    </script>
節點操作方法使用分析:
  • 創建節點最常用的就是創建元素節點和文本節點,而創建屬性節點完全可以用setAttribute()代替。添加節點的方法非常有用,創建新節點和克隆節點都離不開該類方法。
  • 使用時,不要用document.添加節點或者document.刪除節點這種方式,雖然不會報錯,但會找不到節點。這是因爲DOM節點是有層次之分的,所以才需要調用獲取元素節點方法來定位節點位置,並以此來獲取屬性、子節點和相關層次節點。所以執行添加子節點、刪除子節點、刪除屬性節點等操作都基於調用它們的元素節點,不然無法定位元素節點。尤其是在刪除某個節點時,一旦元素節點定位錯誤,則會找不到該節點。  關於document對象,它是作爲整個文檔,所以直接用它來操作節點是不行的,如果要操作HTML節點,應該使用document.documentElement來拿到根元素節點<HTML>,獲取body使用document.body
  • 關於replace()和cloneNode()方法,替換節點方法會把新節點直接放在要替換的節點那裏,相當於直接搬走了。克隆節點方法只是返回調用該方法的元素節點副本,分兩種克隆模式,一種包括子節點,一種只包含當前節點。但兩種節點都不能克隆事件,所以要注意。
  • 要嚴格注意空白文本節點問題,這是個坑。如果想拿到文本節點,可以採用nodeType == 3 來判斷是不是文本節點類型。

DOM操作屬性節點

  • 屬性是元素的一部分,所以只有獲得元素節點後,才能獲取和設置屬性節點。
getAttribute("屬性名") 通過指定屬性名,獲取屬性值。
setAttribute("屬性名","新屬性值") 如果屬性名存在,則更改屬性值。如果不存在,則創建一個新屬性並賦值。
簡便形式:element.屬性名 可以獲取和設置指定屬性的屬性值。但該屬性必須存在。
element.removeAttribute("屬性") 刪除元素節點的指定屬性名
element.attributes 返回元素節點中包含所有屬性的集合
 <input type="text" id="in" name="username" value="用戶">用戶
        <script>
            var inNode = document.getElementById("in"); //獲取元素節點
            //修改屬性值
            inNode.setAttribute("value", "新用戶");
            inNode.setAttribute("type", "button");
            console.log(inNode.getAttribute("value") + "," + inNode.getAttribute("type"));
            //添加新屬性
            inNode.setAttribute("newAttr", "瞎搞的");
            //簡便方式
            inNode.type = "radio";
            inNode.value = "單選框";
            console.log("簡便方式:" + inNode.type + "," + inNode.value);

            inNode.removeAttribute("name"); //刪除name屬性
            //獲取當前元素節點的所有屬性
            var allAttr = inNode.attributes;
           for(var i = 0; i < allAttr.length; i++){
               console.log(allAttr[i]);//打印屬性到控制檯
           }
        </script>
在節點方法中還有用於判斷屬性和檢測屬性的方法,可以自行測驗。




DOM操作文本節點

  • DOM將元素中的文本內容當作節點層次之一,即文本節點,文本節點是TextNode對象。
  • 下面文本節點的屬性我只列出了一個文本節點獨有屬性data,但文本節點也是Node對象,所以依然可用其他節點屬性,例如nodeName/Type/Value、獲取相關層次節點等屬性,而length屬性和data.length差不多。
  • 文本節點中最容易出現的兼容問題就是空白文本節點,後面會說到怎麼解決。
  • 除了通過文本節點的方法和屬性來處理文本節點(前提是要獲取到文本節點);還可以將文本內容提取成字符串,處理後,再放回去。關於這兩種操作的用法後面會依次介紹。
文本節點屬性和方法 功能描述

data  

設置或獲取 TextNode 對象的值。
appendData(string)  添加字符串到文本節點末尾處。
insertData(offset, string) 從offset指定位置插入string
deleteData(offset, count) 從offset起刪除count個字符
replaceData(off,count,string) 從off起將count個字符用string替換
splitText(offset) 從offset起將文本節點分割
substringData(offset, count) 返回從offset起的count個字符

關於空白文本節點

  • 導致空白文本節點的原因:當標籤換行,就會產生一個換行符,或者打一個空格,瀏覽器解析時會把他們當做空白文本節點。
  • 在獲取第一個子節點時極容易獲取到空白文本節點。那怎麼避免空白文本節點呢?
  • 一是所有標籤寫一行,但這不符合代碼美感。
  • 二是將文本內容單獨存儲在一個元素子節點中,避免元素子節點同時存在文本節點和元素節點,這樣再通過firstElementChild和children等屬性就只拿到元素節點,再單獨對該節點進行處理。
 <!-- 注意換行符,會產生空白文本節點 -->
        <div id="p_1">
            <p>文本A</p>
        </div>
        <div id="p_2"><p>文本D</p></div> <!-- 不換行 -->
        <script>
            //拿到元素節點下的所有子節點
            var p1 = document.getElementById("p_1").childNodes;
            var p2 = document.getElementById("p_2").childNodes;
            console.log(p1); //[text, p, text]
            console.log(p2); //[p]        
        </script>
採用第二種方式來避免文本節點,實例如下:
 <!-- 換行符會產生空白文本節點,採用獲取元素節點 -->
        <div id="p_2">
            <div>面朝大海</div>
            <p>春暖化開</p>
        </div>
        <script>
            //獲取所有子節點
            var cn = document.getElementById("p_2").childNodes;
            for(var i = 0; i < cn.length; i++){
                console.log(cn[i]);
            }
            //通過判斷節點類型,過濾文本節點
            for(var i = 0; i < cn.length; i++){
                //節點類型不爲3,纔打印節點信息
                if(cn[i].nodeType != 3){
                    console.log(cn[i]);
                }
            }
等同於children屬性獲取所有元素子節點。


解決空白節點後,下面開始操作文本節點,這裏採用文本節點的方法來處理文本內容,使用方法類似於字符串。下面是一個綜合案例:
<!-- 標籤之間存在空白文本節點 -->
        <div id="p_2">
            <div>面朝大海</div>
            <p>春暖化開</p>
        </div>
        <button onclick="appendStr()">添加文本</button>
        <button onclick="insertStr()">插入文本</button>
        <button onclick="deleteStr()">刪除指定文本</button>
        <button onclick="replaceStr()">替換文本</button>
        <button onclick="split()">切割文本</button>
        <button onclick="subString()">截取前2個文本字符並返回</button>
        <script>
            var cd = document.getElementById("p_2").children; //獲取所有的有效元素子節點,全局變量
            //給所有的文本節點增加一段話
            function appendStr(){
                for(var i = 0; i < cd.length; i++){
                    //獲取每個元素子節點的第一個子節點,這裏是文本節點
                    var tmp = cd[i].firstChild;
                    tmp.appendData("給文本節點中附加一小段話~");
                }
            }
            //從文本節點第一個字符開始插入
            function insertStr(){
                for(var i = 0; i < cd.length; i++){
                    //拿到每個元素子節點的第一個子節點,這裏是文本節點
                    var tmp = cd[i].firstChild;
                    tmp.insertData(0, "從第一個字符插入文本");
                } 
            }
            //刪除[0, 2)區間的字符文本
            function deleteStr(){
                for(var i = 0; i < cd.length; i++){
                    var tmp = cd[i].firstChild;
                    tmp.deleteData(0, 2);
                } 
            }
            //[0,2)區間用replace字符串代替
            function replaceStr(){
                for(var i = 0; i < cd.length; i++){
                    var tmp = cd[i].firstChild;
                    tmp.replaceData(0, 2, "replace");
                } 
            }
            //把文本節點從中間切割成兩部分
            function split(){
                for(var i = 0; i < cd.length; i++){
                    var tmp = cd[i].firstChild;
                    tmp.splitText(tmp.data.length/2);
                } 
            }
            //截取文本節點的[0, 2)區間字符
            function subString(){
                for(var i = 0; i < cd.length; i++){
                    var tmp = cd[i].firstChild;
                    tmp.data = tmp.substringData(0,2); 
                } 
            } 
        </script>
操作文本節點實例使用心得
  • 上面案例是對所有指定的文本節點進行批量操作,如果只想對一個文本節點操作,可以給所處的元素節點加上id屬性,單獨調用處理。
  • 如果想創建一個文本節點添加到指定元素節點中,可以使用document.createTextNode()方法,這個方法在前面節點操作中提到過。
  • 關於data屬性,它能設置和獲取文本節點值,使用的是字符串形式。data和innerText都可以獲取文本內容,但data是文本節點的屬性,作用於單一文本節點。而innerText是元素節點屬性,是用於獲取整個元素節點內部的文本內容。當某個元素節點的唯一子節點是文本節點時,那麼innerText的效果就和data差不多。
  • 關於切割文本用法,切割後的文本內容依然是在一個元素子節點,所以頁面看不出切割效果,可以用瀏覽器打開控制檯查看網頁文件。

文本節點使用字符串來處理方式流程:
  • 獲取文本節點的處理文本內容,對文本內容進行處理後,再將新內容傳入文本節點中。設置和獲取文本節點的文本內容除了使用TextNode.data屬性,還能通過元素節點的innerText 和 innerTML屬性,它們返回的也是字符串。

InnerText 和InnerHTML的區別:

  • innerText:設置或獲取元素節點中所有的文本內容。
  • innerHTML:設置或獲取元素節點內部的所有HTML代碼。
  • innerText和InnerHTML賦值時會覆蓋元素節點內部的所有內容,要注意!所以,當元素內部有許多節點時,建議將文本內容用div單獨存放,這樣直接賦值時就不會影響到元素節點內部的其他節點。
//獲取文本和HTML代碼
var p2 = document.getElementById("p_2");
console.log(p2.innerText); //獲得該元素節點內部所有文本內容
console.log("========================");
console.log(p2.innerHTML); //獲取該元素節點內部的所有HTML代碼
//innerText賦值,會覆蓋內部
p2.innerText = "新的文本內容會覆蓋元素節點";
console.log(p2.innerText);
//innerHTML賦值。只是這個賦值的HTML代碼會被解析
id_div_1.innerText = "<h3>傳入HTML代碼</h3>";
console.log(p2.innerHTML);
【此外,還有outerText和outerHTML這兩個屬性,這兩個賦值時會包含自身標籤,也就是賦值會覆蓋自己,不推薦使用】

拿到文本內容,使用字符串進行處理,再賦值回去。
    <div id="div_1">
        <div>面朝大海的人</div>
        <p>春暖化開的國</p>
    </div>
    <button onclick="appendTest()">添加文本</button>
    <button onclick="replaceTest()">替換文本</button>
    <button onclick="deleteTest()">刪除前兩位文本</button>
    <script>
        var divs = document.getElementById('div_1'); //全局變量
        //這裏使用innerHTML的作用和innerText是一樣的,因爲沒有包含HTML代碼
        //用replace字符串替換前兩位
        function replaceTest(){
            var intext = divs.children[0].innerHTML;
            //截取[0,2)的字符,用replace代替該字符
           var tmp = intext.replace(intext.substring(0,2), "replace");
           //處理過的字符串放回去
           divs.children[0].innerHTML = tmp;
        }
        //添加文本
        function appendTest(){
            var intext = divs.children[0].innerHTML;
           //處理過的字符串放回去
           divs.children[0].innerHTML = "加上一段話~" + intext;;
        }
        //文本內容刪除前兩個字符
        function deleteTest(){
            var cd = divs.children;
            //處理所有子節點的文本節點
            for(var i = 0; i < cd.length; i++){
                var text = cd[i].firstChild;
                var tx = text.data.substring(2); //從第二位開始截取,忽略掉前兩位
                text.data = tx; //把處理的文本內容賦給文本節點
                //還有種刪除方式:把某一段需要刪除的截取出來,然後用repalce(截取的,"")用空字符串替換成需要刪除的字符串,達到刪除效果。
            }
        }
    </script>

文本內容處理方式總結

  • 使用文本節點的基本方法處理文本內容效率很高,但實現的功能較少,也就侷限於增刪改。
  • 將文本節點的內容轉成字符串,以字符串形式來處理文本內容,可以實現很多功能,還支持正則表達式。但效率沒有直接操作文本節點高,因此在此過程中會多次生成字符串。
  • 如果只想對文本內容進行簡單的增刪改,文本節點自帶方法就足夠了,但前提是要拿到文本節點,不然用不了。如果要對文本內容進行深層次處理,就轉成字符串形式來處理。
  • 根據你的需求來決定~
 
      關於DOM操作節點的詳細使用方式就介紹完成了,另外還有修改CSS樣式、DOM事件處理還沒說到,放在後續博客中。尤其是事件,非常重要,我上面的一些代碼實例中就用到幾個單擊事件。後續博客會詳細介紹每一種事件的使用方式。
      最後,我想說的是:不能光看概念,代碼一定要多寫,寫得多了自然就理解了,不然光靠理論理解是無法掌握DOM操作節點的細節問題的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章