在前幾篇文章中我們都在介紹屬性的新增修改,但若我們想使用 JavaScript 動態新增元素到頁面上某處的話,除了使用 innerHTML
外還有什麼方法呢?
其實在 DOM 中提供了許多 API 讓我們可以操作 Node (節點),下面就讓我們用實際範例說明要如何從無到有新增一個元素吧!
假設今天有一 div
,我們想用 JavaScript 在 div
中加入標題和兩個 input 元素:
<!-- 原始 HTML 程式 -->
<div id="container">
</div>
<!-- 動態加入標題和兩個 input 最終程式結構如下 -->
<div id="container">
<h>請輸入姓名</h>
<input value="111">
<input type="button" value="確認">
</div>
要在原有的結構中加入新的節點,第一步要做的是「建立節點」!
前面我們有說過 Node 主要分為四種:document、element (元素節點)、text (文字節點)、及 attribute (屬性節點),除了 document 無法創造外,其他三種節點都有相對應的 DOM API。
document.createElement(要建立的元素標籤名)
document.createTextNode(文字內容)
document.createAttribute(屬性名)
而在本範例中,我們需要新增的元素有三個,其中包含的節點如下:
h
、一個 text node 請輸入姓名
input
、一個 attribute node value
input
、兩個 attribute node type
和 value
話不多說,現在就先建立第一個「標題 h」需要用到的節點:
// 新增一個元素節點,標籤為 h
let h = document.createElement('h');
// 新增一個文字節點,內容為 "請輸入姓名"
let hText = document.createTextNode('請輸入姓名');
補充:在開發中通常會將建立好的節點指到變數中,這是因為我們要將各個不同的節點組合起來成為所需的架構,使用變數可以讓程式碼更清晰。
現在我們已經有了兩個標題所需的節點,接下來需要讓網頁知道這兩個節點是「一組」的,在 JavaScript 中用來表示兩節點組合關係的方式有以下幾種:
指定節點.appendChild(新節點)
,聽起來好像有點繞口,白話一點來說就是將新節點放在指定節點「最後一個小孩」的位置。指定節點.insertBefore(新節點)
,這個就比較單純了,意思就是將某節點插到另一個節點之前的位置。元素節點.setAttributeNode(屬性節點)
,從 HTML 結構中我們可以觀察到元素節點和文字節點間的關係都是父子或兄弟,而屬性節點則不同,它無法單獨存在,所以 setAttributeNode
是專門用來新增屬性節點的一個用法。回到範例,接下來我們要開始組合 h
和 hText
了:
可以看到在題目結構中,h
標籤和 hText
文字內容屬於父子關係,所以可以直接以 appendChild
將文字加到 h
中。
h.appendChild(hText);
現在我們的第一個元素已經組合好了,也就是 <h>請輸入姓名</h>
最後一個步驟是決定要將這個元素放在頁面上的哪裡!依照結構來看標題元素是 #container
的第一個子元素,不過目前後面兩個元素都還沒被我們新增,所以可以直接使用 appendChild
按順序加上去。
document.getElementById('container').appendChild(h);
到此為止我們已經將第一個標題元素新增好了,接下來兩個 input 元素可以直接以此類推,先來新增 input 框需要的節點 - 一個 element node input
、一個 attribute node value
:
let input = document.createElement('input');
let attr = document.createAttribute('value');
關於屬性節點,因為結構與其他節點不同,是 key="value"
結構,所以在 create 後還需要新增屬性值,而方法就是設定該節點的 nodeValue
。
// 設定屬性節點的屬性值
attr.nodeValue = '111';
現在我們已經將節點都新增好了,接下來要用 setAttribute()
將屬性節點放到 input 元素節點中
,再將組合好的整個 input
加到文檔流裡。
// 將屬性節點加到元素節點中
input.setAttributeNode(attr);
// 將整個 input 元素放到 HTML 指定處
document.getElementById('container').appendChild(input);
到這邊為止我們已經完成了兩個元素,剩下最後一個 input button
。
在剛剛新增 input 框時我們用的是「新增屬性節點」的方式,但在屬性很多的元素中要一個一個新增再組合很麻煩,所以這邊我們使用另一個方式,也就是直接用 element.屬性名 = "屬性值"
來為元素節點加屬性。
接下來就來新增第三個元素吧:
// 不新增屬性節點,所以只需新增一個元素節點
let btn = document.createElement('input');
// 直接以 element.屬性名 = "屬性值" 的方式來加入屬性
btn.type = "button";
btn.value = "確認";
// 將組合好的元素放到文檔流 (HTML) 指定處
document.getElementById('container').appendChild(btn);
到這邊為止我們的三個元素都被動態的加到網頁中啦!
// 新增 h 標題
// 建立 h 所需的節點 (h 元素節點和文字節點)
let h = document.createElement('h');
let hText = document.createTextNode('請輸入姓名');
// 將文字節點放到 h 元素節點中
h.appendChild(hText);
// 將組合好的元素放到文檔流 (HTML) 指定處
document.getElementById('container').appendChild(h);
// 新增 input 框
// 建立 input 所需的節點 (元素節點和屬性節點)
let input = document.createElement('input');
let attr = document.createAttribute('value');
// 將屬性值塞到屬性節點中
attr.nodeValue = '111';
// 將屬性節點加到元素節點中
input.setAttributeNode(attr);
// 將組合好的元素放到文檔流 (HTML) 指定處
document.getElementById('container').appendChild(input);
// 新增 input button
// 建立所需的節點 (這邊屬性結點使用另一種方法,所以不新增)
let btn = document.createElement('input');
// 直接以 element.屬性名 = "屬性值" 的方式來加入屬性
btn.type = "button";
btn.value = "確認";
// 將組合好的元素放到文檔流 (HTML) 指定處
document.getElementById('container').appendChild(btn);
上面範例要新增的 HTMl 結構較單純,而當結構很複雜時,例如需要新增一個擁有很多子孫元素的 div
元素到頁面上時,以每個都 create
的方式會非常繁雜。
在實際開發中我們最常用的還是以 createElemnt
結合 innerHTML
來做使用,我們可以先 create 最外層的元素,再將其他的子元素 HTMl code 以 innerHTML
的方式加入,這樣可以省掉不少添加和組合的時間。
範例:
在 container 中新增一個有 input 框、多選框、及按鈕的表單 (form)。
// 新增 form element node
let form = document.createElement('form');
// 將 html code 加到 form 中
form.innerHTML = '<span>請輸入姓名</span><br/><input value=""><br/>' +
'<div><input type="checkbox" name="check"/><label>男</label></div>' +
'<div><input type="checkbox" name="check"/><label>女</label></div>' +
'<input type="button" value="確認">';
// 將 form 加到頁面中
document.getElementById('container').appendChild(form);
上一篇:[快速入門前端 62] JavaScript:DOM (4) 修改元素的屬性值
下一篇:[快速入門前端 64] JavaScript:DOM (5) 節點的 CRUD - 修改、刪除
系列文章列表:[快速入門前端] 系列文章索引列表