Skip to content

DOM 節點屬性:textContent、innerHTML 與 setAttribute

節點的屬性:textContent 與 innerHTML

在前面曾介紹過 DOM 的觀念DOM 的選取方式,若是不清楚的!請至前面兩篇文章複習一下。現在,Away 要帶各位來看看如何操作 DOM 去更改網頁的內容。

寫入文字

html
<div class="box" id="Box">
  <h1 class="box-title">title</h1>
  <a class="box-link" href="javascript:;"></a>
</div>
js
const elemBox = document.querySelector('#Box');
const elemTitle = elemBox.querySelector('.box-title');
const elemLink = elemBox.querySelector('.box-link');

textContent

代表設定文字內容。

js
elemTitle.textContent = '我是標題';
elemLink.textContent = '前往 Yahoo!';

innerText

代表設定文字內容。

js
elemTitle.innerText = '我是標題';

innerHTML

代表在一個 DOM 內的全部 HTML 標籤和文字,但不包含所選取 DOM 的 HTML 標籤。

js
elemLink.innerHTML = '<em>Go To PCHome</em>';

outerHTML

代表在一個 DOM 內的全部 HTML 標籤和文字,包含所選取 DOM 的 HTML 標籤。

js
elemLink.outerHTML = '<em>Go To PCHome</em>';

注意

outerHTML 賦值後,原本那個元素就 被替換掉了,之前存進變數的 elemLink 也會指向已離開文件的舊節點。之後再對它操作,畫面不會有反應。

讀取文字

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>
js
const elemBox = document.querySelector('#Box');
const elemTitle = elemBox.querySelector('.box-title');
const elemLink = elemBox.querySelector('.box-link');

textContent

代表了 DOM 或其後代的文字內容。

js
// JavaScript 課程 JS
console.log(elemTitle.textContent);

innerText

代表 DOM 及其後代之已渲染文字內容的屬性。

js
// JavaScript 課程
console.log(elemTitle.innerText);

差別就在這裡:<small> 被 CSS 隱藏了,textContent 照樣讀得到,innerText 只讀 看得見 的文字。

innerHTML

代表在一個 DOM 內的全部 HTML 標籤和文字,但不包含所選取 DOM 的 HTML 標籤。

js
/*
  <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 標籤。

js
/*
  <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)也能讀寫,例如:srchrefaltdisabled

直接賦值

常見的標準屬性可以像一般物件屬性那樣存取:

js
const elemPic = document.querySelector('#Pic');

elemPic.src = './images/large.jpg';
elemPic.alt = '大圖';

// ./images/large.jpg
console.log(elemPic.src);

setAttribute()

以屬性名稱與值兩個參數設定屬性,自訂屬性也能設定。

js
const elemLink = document.querySelector('.box-link');

elemLink.setAttribute('href', 'https://tw.yahoo.com');
elemLink.setAttribute('target', '_blank');
elemLink.setAttribute('data-id', '7533967');

getAttribute()

讀取指定屬性的值,屬性不存在時回傳 null

js
// https://tw.yahoo.com
console.log(elemLink.getAttribute('href'));

removeAttribute() 與 hasAttribute()

js
// 是否有 target 屬性:true
console.log(elemLink.hasAttribute('target'));

// 移除屬性
elemLink.removeAttribute('target');

小提醒

把屬性設成空字串(setAttribute('target', ''))不等於移除,屬性本身還在。要真的拿掉請用 removeAttribute()

classList 控制 class

js
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 控制行內樣式

js
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 存取,這在 事件委派 中很常用:

html
<button id="Btn" data-id="7533967" data-user-name="Away">按鈕</button>
js
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 與直接賦值哪個好?

常見屬性例如:srchref 直接賦值最直覺;自訂屬性或 data- 屬性用 setAttribute() 較保險。要移除屬性請用 removeAttribute(),設成空字串屬性仍然存在。

要換 class 該用 className 還是 classList?

classList。它提供 add()remove()toggle()contains() 等方法,能單獨增減某個 class;className 是整串字串,賦值會覆蓋掉原有的所有 class。

延伸閱讀