1. 給開發者的 Web 技術文件
  2. CSS
  3. Guides
  4. Text
  5. 處理空白

此頁面由社群從英文翻譯而來。了解更多並加入 MDN Web Docs 社群。

View in English Always switch to English

處理空白

問題說明

DOM 裡的空白字元會讓處理節點結構時增加不少麻煩。Mozilla 相關軟體中,原始文件裡所有空白字元都會在 DOM 中出現(不包括標籤內含的空白字元)。這樣的處理方式有其必要,一方面編輯器中可逕行排列文字、二方面 CSS 裡的 white-space: pre 也才能發揮作用。 如此一來就表示:

  • 有些空白字元會自成一個文字節點。
  • 有些空白字元會與其他字串合成一個文字節點。

換句話說,下面這段程式碼的 DOM 節點結構就如附圖一般,其中「\n」代表換行字元:

html
<!doctype html>
<html lang="en-US">
 <head>
 <meta charset="UTF-8" />
 <title>My Document</title>
 </head>
 <body>
 <h1>Header</h1>
 <p>Paragraph</p>
 </body>
</html>

[画像:The DOM tree representing a simple HTML document]

這麼一來,要使用 DOM 遊走於節點結構間又不想要無用的空白字元時,會有點困難。

助你一臂之力

以下的 JavaScript 程式碼定義了許多函式,讓你處理 DOM 中的空白字元時能輕鬆點:

js
/**
 * 以下所謂的「空白字元」代表:
 * "\t" TAB \u0009 (移位字元)
 * "\n" LF \u000A (換行字元)
 * "\r" CR \u000D (歸位字元)
 * " " SPC \u0020 (真正的空白)
 *
 * 不包括 JavaScript 的「\s」,因為那代表如不斷行字元等其他字元。
 */
/**
 * 測知某節點的文字內容是否全為空白。
 *
 * @param nod `CharacterData` 類的節點(如 `Text`、`Comment` 或 `CDATASection`)。
 * @return 若 `nod` 的文字內容全為空白則回傳 `true`,否則回傳 `false`。
 */
function isAllWs(nod) {
 return !/[^\t\n\r ]/.test(nod.textContent);
}
/**
 * 測知是否該略過某節點。
 *
 * @param nod DOM1 |Node| 物件
 * @return 若 |Text| 節點內僅有空白字元或為 |Comment| 節點時,傳回 true,
 * 否則傳回 false。
 */
function isIgnorable(nod) {
 return (
 nod.nodeType == 8 || // 註解節點
 (nod.nodeType == 3 && isAllWs(nod))
 ); // 僅含空白字元的文字節點
}
/**
 * 此為會跳過空白字元節點及註解節點的 |previousSibling| 函式
 * ( |previousSibling| 是 DOM 節點的特性值,為該節點的前一個節點。)
 *
 * @param sib 節點。
 * @return 有兩種可能:
 * 1) |sib| 的前一個「非空白、非註解」節點(由 |is_ignorable| 測知。)
 * 2) 若該節點前無任何此類節點,則傳回 null。
 */
function nodeBefore(sib) {
 while ((sib = sib.previousSibling)) {
 if (!isIgnorable(sib)) {
 return sib;
 }
 }
 return null;
}
/**
 * 此為會跳過空白字元節點及註解節點的 |nextSibling| 函式
 *
 * @param sib 節點。
 * @return 有兩種可能:
 * 1) |sib| 的下一個「非空白、非註解」節點。
 * 2) 若該節點後無任何此類節點,則傳回 null。
 */
function nodeAfter(sib) {
 while ((sib = sib.nextSibling)) {
 if (!isIgnorable(sib)) {
 return sib;
 }
 }
 return null;
}
/**
 * 此為會跳過空白字元節點及註解節點的 |lastChild| 函式
 * ( lastChild| 是 DOM 節點的特性值,為該節點之中最後一個子節點。)
 *
 * @param par 節點。
 * @return 有兩種可能:
 * 1) |par| 中最後一個「非空白、非註解」節點。
 * 2) 若該節點中無任何此類子節點,則傳回 null。
 */
function lastChild(par) {
 let res = par.lastChild;
 while (res) {
 if (!isIgnorable(res)) {
 return res;
 }
 res = res.previousSibling;
 }
 return null;
}
/**
 * 此為會跳過空白字元節點及註解節點的 |firstChild| 函式
 *
 * @param par 節點。
 * @return 有兩種可能:
 * 1) |par| 中第一個「非空白、非註解」節點。
 * 2) 若該節點中無任何此類子節點,則傳回 null。
 */
function firstChild(par) {
 let res = par.firstChild;
 while (res) {
 if (!isIgnorable(res)) {
 return res;
 }
 res = res.nextSibling;
 }
 return null;
}
/**
 * 此為傳回值不包含文字節點資料的首尾所有空白字元、
 * 並將兩個以上的空白字元縮減為一個的 |data| 函式。
 *( data 是 DOM 文字節點的特性值,為該文字節點中的資料。)
 *
 * @param txt 欲傳回其中資料的文字節點
 * @return 文字節點的內容,其中空白字元已依前述方式處理。
 */
function dataOf(txt) {
 let data = txt.textContent;
 data = data.replace(/[\t\n\r ]+/g, " ");
 if (data[0] === " ") {
 data = data.substring(1, data.length);
 }
 if (data[data.length - 1] === " ") {
 data = data.substring(0, data.length - 1);
 }
 return data;
}

以下程式碼示範上述函式的應用方法,在節點結構中依序檢查、找出內容為 "This is the third paragraph" 的節點,並修改其 class 屬性及文字內容。

js
let cur = firstChild(document.getElementById("test"));
while (cur) {
 if (dataOf(cur.firstChild) === "This is the third paragraph.") {
 cur.className = "magic";
 cur.firstChild.textContent = "This is the magic paragraph.";
 }
 cur = nodeAfter(cur);
}

Help improve MDN

Learn how to contribute

This page was last modified on by MDN contributors.

AltStyle によって変換されたページ (->オリジナル) /