Element:outerHTML 屬性

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

警告:此屬性將輸入解析為 HTML,並將結果寫入 DOM。像這樣的 API 被稱為注入槽,如果輸入最初來自攻擊者,它們可能是跨站指令碼(XSS)攻擊的潛在途徑。

您可以透過始終分配 TrustedHTML 物件而不是字串並強制執行可信型別來減輕這種風險。有關更多資訊,請參閱安全注意事項

Element 介面的 outerHTML 屬性獲取或設定元素及其後代的 HTML 或 XML 標記,這兩種情況下都會省略任何影子根

要獲取或設定元素的內容,請改用 innerHTML 屬性。

獲取此屬性會返回一個字串,其中包含 element 及其後代的 HTML 序列化。

設定此屬性接受 TrustedHTML 物件或字串。輸入被解析為 HTML 並替換元素及其所有後代。當設定為 null 值時,該 null 值將轉換為空字串(""),因此 element.outerHTML = null 等同於 element.outerHTML = ""

異常

NoModificationAllowedError DOMException

如果嘗試在作為 Document 的直接子元素的元素(例如 Document.documentElement)上設定 outerHTML,則會丟擲此錯誤。

SyntaxError DOMException

如果嘗試使用格式不正確的 XML 輸入設定 outerHTML,則會丟擲此錯誤。

TypeError

如果在可信型別CSP 強制執行且未定義預設策略時將屬性設定為字串,則丟擲此錯誤。

描述

outerHTML 獲取元素的序列化,或者設定應解析的 HTML 或 XML,以替換元素父級中的元素。

如果元素沒有父節點,設定其 outerHTML 屬性將不會更改它或其後代。例如

js
const div = document.createElement("div");
div.outerHTML = '<div class="test">test</div>';
console.log(div.outerHTML); // output: "<div></div>"

此外,雖然元素將在文件中被替換,但其 outerHTML 屬性被設定的變數仍將保留對原始元素的引用

js
const p = document.querySelector("p");
console.log(p.nodeName); // shows: "P"
p.outerHTML = "<div>This div replaced a paragraph.</div>";
console.log(p.nodeName); // still "P";

轉義屬性值

返回的值將轉義 HTML 屬性中的某些值。此處我們看到 & 字元被轉義

js
const anchor = document.createElement("a");
anchor.href = "https://mdn.club.tw?a=b&c=d";
console.log(anchor.outerHTML); // output: "<a href='https://mdn.club.tw?a=b&amp;c=d'></a>"

一些瀏覽器還將屬性值中出現的 <> 字元序列化為 &lt;&gt;(參見瀏覽器相容性)。這是為了防止潛在的安全漏洞(變異 XSS),攻擊者可以精心製作輸入以繞過淨化函式,從而實現跨站指令碼 (XSS) 攻擊。

Shadow DOM 考慮事項

從屬性讀取的 DOM 樹的序列化不包括影子根。如果要獲取包含影子根的元素的 HTML 序列化,則必須改用 Element.getHTML() 方法。請注意,這將獲取元素的內容

類似地,當使用 outerHTML 設定元素內容時,HTML 輸入會被解析為不包含影子根的 DOM 元素。例如,<template> 會被解析為 HTMLTemplateElement,無論是否指定了 shadowrootmode 屬性。如果您想使用包含宣告性影子根的 HTML 輸入來設定元素的內容,則必須改用 Element.setHTMLUnsafe()ShadowRoot.setHTMLUnsafe()

安全注意事項

outerHTML 屬性是跨站指令碼 (XSS) 攻擊的潛在載體,因為它可用於將使用者提供的潛在不安全字串注入 DOM。雖然該屬性確實阻止了 <script> 元素在注入時執行,但它容易受到攻擊者精心製作 HTML 以執行惡意 JavaScript 的許多其他方式的影響。例如,以下示例將執行 error 事件處理程式中的程式碼,因為 <img> src 值不是有效的影像 URL

js
const name = "<img src='x' onerror='alert(1)'>";
element.outerHTML = name; // shows the alert

您可以透過始終分配 TrustedHTML 物件而不是字串,並透過 require-trusted-types-for CSP 指令強制執行可信型別來緩解這些問題。這確保輸入透過轉換函式傳遞,該函式有機會在注入之前淨化輸入以刪除潛在危險的標記。

示例

獲取元素的序列化

讀取 outerHTML 會導致使用者代理序列化元素。

給定以下 HTML

html
<div id="example">
  <p>Content</p>
  <p>Further Elaborated</p>
</div>

您可以按所示獲取並記錄 <div> 的標記

js
const myElement = document.querySelector("#example");
const contents = myElement.outerHTML;
console.log(contents);
// '<div id="example">\n  <p>Content</p>\n  <p>Further Elaborated</p>\n</div>'

替換元素

在此示例中,我們將透過將 HTML 分配給元素的 outerHTML 屬性來替換 DOM 中的元素。為了減輕 XSS 的風險,我們將首先從包含 HTML 的字串建立一個 TrustedHTML 物件,然後將該物件分配給 outerHTML

可信型別尚未在所有瀏覽器中受支援,因此我們首先定義可信型別小型填充。這可以作為可信型別 JavaScript API 的透明替代品。

js
if (typeof trustedTypes === "undefined")
  trustedTypes = { createPolicy: (n, rules) => rules };

接下來,我們建立一個 TrustedTypePolicy,它定義了一個 createHTML(),用於將輸入字串轉換為 TrustedHTML 例項。通常,createHTML() 的實現使用像 DOMPurify 這樣的庫來清理輸入,如下所示

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

然後我們使用這個 policy 物件從潛在不安全的輸入字串建立 TrustedHTML 物件,並將結果分配給元素。

js
// The potentially malicious string
const untrustedString = "<p>I might be XSS</p><img src='x' onerror='alert(1)'>";

// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);

// Inject the TrustedHTML (which contains a trusted string)
const element = document.querySelector("#container");
element.outerHTML = trustedHTML; // Replaces the element with id "container"

// Note that the  #container div is no longer part of the document tree,

警告:雖然您可以直接將字串分配給 outerHTML,但如果要插入的字串可能包含潛在惡意內容,這會帶來安全風險。您應該使用 TrustedHTML 來確保內容在插入之前經過淨化,並且應該設定 CSP 頭部以強制執行可信型別

規範

規範
HTML
# dom-element-outerhtml

瀏覽器相容性

另見