DOM 節點屬性:textContent、innerHTML 與 setAttribute
在前面曾介紹過 DOM 的觀念、DOM 的選取方式,若是不清楚的!請至前面兩篇文章複習一下。現在,Away 要帶各位來看看如何操作 DOM 去更改網頁的內容。
寫入文字
<div class="box" id="Box">
<h1 class="box-title">title</h1>
<a class="box-link" href="javascript:;"></a>
</div>const elemBox = document.querySelector('#Box');
const elemTitle = elemBox.querySelector('.box-title');
const elemLink = elemBox.querySelector('.box-link');textContent
代表設定文字內容。
elemTitle.textContent = '我是標題';
elemLink.textContent = '前往 Yahoo!';innerText
代表設定文字內容。
elemTitle.innerText = '我是標題';innerHTML
代表在一個 DOM 內的全部 HTML 標籤和文字,但不包含所選取 DOM 的 HTML 標籤。
elemLink.innerHTML = '<em>Go To PCHome</em>';outerHTML
代表在一個 DOM 內的全部 HTML 標籤和文字,包含所選取 DOM 的 HTML 標籤。
elemLink.outerHTML = '<em>Go To PCHome</em>';注意
outerHTML 賦值後,原本那個元素就 被替換掉了,之前存進變數的 elemLink 也會指向已離開文件的舊節點。之後再對它操作,畫面不會有反應。
讀取文字
<div class="box" id="Box">
<h1 class="box-title">
JavaScript 課程 <small style="display: none;">JS</small>
</h1>
<a class="box-link" href="http://tw.yahoo.com">前往 Yahoo!</a>
</div>const elemBox = document.querySelector('#Box');
const elemTitle = elemBox.querySelector('.box-title');
const elemLink = elemBox.querySelector('.box-link');textContent
代表了 DOM 或其後代的文字內容。
// JavaScript 課程 JS
console.log(elemTitle.textContent);innerText
代表 DOM 及其後代之已渲染文字內容的屬性。
// JavaScript 課程
console.log(elemTitle.innerText);差別就在這裡:<small> 被 CSS 隱藏了,textContent 照樣讀得到,innerText 只讀 看得見 的文字。
innerHTML
代表在一個 DOM 內的全部 HTML 標籤和文字,但不包含所選取 DOM 的 HTML 標籤。
/*
<h1 class="box-title">JavaScript 課程 <small style="display: none;">JS</small></h1>
<a class="box-link" href="http://tw.yahoo.com">前往 Yahoo!</a>
*/
console.log(elemBox.innerHTML);outerHTML
代表在一個 DOM 內的全部 HTML 標籤和文字,包含所選取 DOM 的 HTML 標籤。
/*
<div class="box" id="Box">
<h1 class="box-title">JavaScript 課程 <small style="display: none;">JS</small></h1>
<a class="box-link" href="http://tw.yahoo.com">前往 Yahoo!</a>
</div>
*/
console.log(elemBox.outerHTML);四個屬性的比較
| 屬性 | 含元素本身的標籤 | 會解析 HTML 標籤 | 只算看得見的文字 |
|---|---|---|---|
textContent | 否 | 否 | 否 |
innerText | 否 | 否 | 是 |
innerHTML | 否 | 是 | 否 |
outerHTML | 是 | 是 | 否 |
該選哪一個
- 寫入純文字 →
textContent,最快也最安全。 - 需要寫入標籤 →
innerHTML,但內容不可以是使用者輸入的原始字串。 - 只是想讀畫面上看到的文字 →
innerText。
安全性注意
把使用者輸入直接塞進 innerHTML,等於允許對方在你的頁面上執行 HTML 與 JavaScript,這就是 XSS(跨站腳本攻擊)。純文字一律改用 textContent。
屬性控制
除了內容,元素上的屬性(Attribute)也能讀寫,例如:src、href、alt、disabled。
直接賦值
常見的標準屬性可以像一般物件屬性那樣存取:
const elemPic = document.querySelector('#Pic');
elemPic.src = './images/large.jpg';
elemPic.alt = '大圖';
// ./images/large.jpg
console.log(elemPic.src);setAttribute()
以屬性名稱與值兩個參數設定屬性,自訂屬性也能設定。
const elemLink = document.querySelector('.box-link');
elemLink.setAttribute('href', 'https://tw.yahoo.com');
elemLink.setAttribute('target', '_blank');
elemLink.setAttribute('data-id', '7533967');getAttribute()
讀取指定屬性的值,屬性不存在時回傳 null。
// https://tw.yahoo.com
console.log(elemLink.getAttribute('href'));removeAttribute() 與 hasAttribute()
// 是否有 target 屬性:true
console.log(elemLink.hasAttribute('target'));
// 移除屬性
elemLink.removeAttribute('target');小提醒
把屬性設成空字串(setAttribute('target', ''))不等於移除,屬性本身還在。要真的拿掉請用 removeAttribute()。
classList 控制 class
const elemBox = document.querySelector('#Box');
// 新增
elemBox.classList.add('is-active');
// 移除
elemBox.classList.remove('is-active');
// 有就移除、沒有就新增,做開關最方便
elemBox.classList.toggle('is-active');
// 是否含有某個 class
console.log(elemBox.classList.contains('is-active'));注意
className 是一整串字串,賦值會覆蓋掉原有的所有 class;要單獨增減某一個,請用 classList。
style 控制行內樣式
const elemBox = document.querySelector('#Box');
elemBox.style.color = '#fff';
elemBox.style.backgroundColor = 'tomato';小提醒
CSS 的 background-color 在 JavaScript 中要寫成小駝峰的 backgroundColor。實務上更建議用 classList 切換 class,把樣式留在 CSS 裡管理。
dataset 讀取 data 屬性
HTML 上以 data- 開頭的自訂屬性,可以透過 dataset 存取,這在 事件委派 中很常用:
<button id="Btn" data-id="7533967" data-user-name="Away">按鈕</button>const elemBtn = document.querySelector('#Btn');
// 7533967
console.log(elemBtn.dataset.id);
// Away,data-user-name 對應 userName
console.log(elemBtn.dataset.userName);常見問題
textContent 與 innerText 有什麼差別?
textContent 回傳所有後代的文字,包含被 CSS 隱藏的部分;innerText 只回傳實際渲染出來的文字,因此會觸發版面計算,讀取成本較高。
什麼時候該用 innerHTML?
只有真的需要寫入 HTML 標籤時才用。純文字請用 textContent,因為 innerHTML 會解析字串中的標籤,若內容來自使用者輸入就有 XSS 風險。
innerHTML 與 outerHTML 差在哪裡?
innerHTML 是元素內部的內容,不含元素本身的標籤;outerHTML 連元素本身一起算。因此對 outerHTML 賦值會把該元素整個替換掉。
setAttribute 與直接賦值哪個好?
常見屬性例如:src、href 直接賦值最直覺;自訂屬性或 data- 屬性用 setAttribute() 較保險。要移除屬性請用 removeAttribute(),設成空字串屬性仍然存在。
要換 class 該用 className 還是 classList?
用 classList。它提供 add()、remove()、toggle()、contains() 等方法,能單獨增減某個 class;className 是整串字串,賦值會覆蓋掉原有的所有 class。