[JavaScript] (Day-17) - DOM 基本操作

Happiness takes no account of time. 幸福不覺光陰過。

由于 HTML 文檔被瀏覽器解析后就是一棵 DOM 樹,要改變 HTML 的結構,就需要通過 JavaScript 來操作 DOM。

操作一個 DOM 節點實際上就是這么幾個操作:

  • 更新:更新該 DOM 節點的內容,相當于更新了該 DOM 節點表示的HTML 的內容;
  • 遍歷:遍歷該 DOM 節點下的子節點,以便進行進一步操作;
  • 添加:在該 DOM 節點下新增一個子節點,相當于動態增加了一個 HTML 節點;
  • 刪除:將該節點從 HTML 中刪除,相當于刪掉了該 DOM 節點的內容以及它包含的所有子節點。

獲取節點元素

在操作一個 DOM 節點前,我們需要通過各種方式先拿到這個 DOM 節點。

最常用的方法是:

  • document.getElementById()
  • document.getElementsByTagName()
  • 以及 CSS 選擇器 document.getElementsByClassName()

由于ID在 HTML 文檔中是唯一的,所以document.getElementById()可以直接定位唯一的一個DOM節點;

document.getElementsByTagName()document.getElementsByClassName()總是返回一組 DOM 節點。要精確地選擇 DOM,可以先定位父節點,再從父節點開始選擇,以縮小范圍。

// 返回ID為'test'的節點:
var test = document.getElementById('test');

// 先定位ID為'test-table'的節點,再返回其內部所有tr節點:
var trs = document.getElementById('test-table').getElementsByTagName('tr');

// 先定位ID為'test-div'的節點,再返回其內部所有class包含red的節點:
var reds = document.getElementById('test-div').getElementsByClassName('red');

// 獲取節點test下的所有直屬子節點:
var cs = test.children;

// 獲取節點test下第一個、最后一個子節點:
var first = test.firstElementChild;
var last = test.lastElementChild;

第二種方法是使用querySelector()querySelectorAll(),需要了解selector語法,然后使用條件來獲取節點,更加方便:

// 通過 querySelector 獲取 ID 為 q1 的節點:
var q1 = document.querySelector('#q1');

// 通過 querySelectorAll 獲取 q1 節點內的符合條件的所有節點:
var ps = q1.querySelectorAll('div.highlighted > p');

更新 DOM

拿到一個 DOM 節點后,我們可以對它進行更新,直接修改節點的文本

方式一:修改innerHTML屬性,這個方式非常強大,不但可以修改一個DOM節點的文本內容,還可以直接通過HTML片段修改DOM節點內部的子樹

// 獲取<p id="p_id">...</p>
var p = document.getElementById('p_id');

// 設置文本為ABC:
p.innerHTML = 'ABC'; // <p id="p-id">ABC</p>

// 設置HTML:
p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
// <p>...</p>的內部結構已修改

方式二: 修改innerTexttextContent屬性,這樣可以自動對字符串進行 HTML 編碼,保證無法設置任何HTML標簽

innerTexttextContent的區別在于讀取屬性時,innerText不返回隱藏元素的文本,而textContent返回所有文本

// 獲取<p id="p_id">...</p>
var p = document.getElementById('p_id');

// 設置文本:
p.innerText = '<script>alert("Hi")</script>';

// HTML被自動編碼,無法設置一個<script>節點:
// <p id="p-id"><script>alert("Hi")</script></p>

插入 DOM

獲得某個 DOM 節點,然后在這個 DOM 節點內插入新的 DOM

方式一:使用appendChild,把一個子節點添加到父節點的最后一個子節點

例如:

<!-- HTML結構 -->
<p id="js">JavaScript</p>
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>

idjs 的標簽插入到 <div>...</div> 便簽最后一項

var js = document.getElementById('js');
var list = document.getElementById('list');
list.appendChild(js);

結果:

<!-- HTML結構 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
    <p id="js">JavaScript</p>
</div>

上面是把已知的元素插入到指定位置,但更多的時候我們會從零創建一個新的節點,然后插入到指定位置:

var list = document.getElementById('list');
var swift = document.createElement('p');
swift.id = 'swift';
swift.innerText = 'Swift';
list.appendChild(swift);

結果:

<!-- HTML結構 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
    <p id="swift">Swift</p>
</div>


方式二: 使用 insertBefore 把子節點插入到指定的位置

使用parentElement.insertBefore(newElement, referenceElement);,子節點會插入到referenceElement之前。

還是以上面的 HTML 為例,假定我們要把Swift插入到Python之前:

<!-- HTML結構 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>
var list = document.getElementById('list');
var ref = document.getElementById('python');
var swift = document.createElement('p');
swift.id = 'swift';
swift.innerText = 'Swift';
list.insertBefore(swift, ref);
<!-- HTML結構 -->
<div id="list">
    <p id="java">Java</p>
    <p id="swift">Swift</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>


刪除DOM

刪除一個節點,首先要獲得該節點本身以及它的父節點,然后,調用父節點的removeChild把自己刪掉

// 拿到待刪除節點:
var self = document.getElementById('to-be-removed');

// 拿到父節點:
var parent = self.parentElement;

// 刪除:
var removed = parent.removeChild(self);
removed === self; // true

注意,當從子節點數組中刪除節點時,需要防止數組越界

<div id="parent">
    <p>First</p>
    <p>Second</p>
</div>

執行刪除操作

var parent = document.getElementById('parent');

parent.removeChild(parent.children[0]);

parent.removeChild(parent.children[1]); // <-- 瀏覽器報錯

報錯原因:

<p>First</p>節點被刪除后,parent.children的節點數量已經從2變為了1,索引[1]已經不存在了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容