深入理解 element.innerHTML
设置和获取元素的 HTML 内容
innerHTML
属性用于设置或获取元素的 HTML 内容。以下是一个基本示例:
<div class="wrapper"></div>
<script>
const wrapperElement = document.getElementsByClassName('wrapper')[0];
wrapperElement.innerHTML = '<h1>Hello World</h1>';
</script>
需要注意以下几点:
innerHTML
字符串必须符合有效的 HTML 语法,否则在旧版本浏览器中可能会出现语法错误。
document.innerHTML
是只读属性,无法直接修改整个文档的 HTML。
为 innerHTML
赋值会移除元素原有的所有子节点,并用新的 HTML 内容替换。
显示 HTML 源码
有时需要在页面上展示 HTML 源码,可以结合 innerHTML
和字符串替换实现:
<div class="wrapper"></div>
<script>
const wrapperElement = document.getElementsByClassName('wrapper')[0];
const htmlContent = document.documentElement.innerHTML;
const encodedHtml = htmlContent.replace(/</g, '<');
document.documentElement.innerHTML = '<pre>' + encodedHtml + '</pre>';
wrapperElement.innerHTML = encodedHtml;
</script>
上述代码首先获取整个文档的 HTML,然后将 <
替换为 <
以进行转义,最后使用 <pre>
标签包裹并设置回去,从而在页面上显示格式化后的 HTML 源码。
引用失效问题
使用 innerHTML
赋值后,之前保存的 DOM 元素引用可能会失效。如下例所示:
<div class="wrapper">
<span>Hello</span>
</div>
<script>
const wrapperElement = document.getElementsByClassName('wrapper')[0];
const textElement = document.getElementsByTagName('span')[0];
wrapperElement.innerHTML += '<h1>World</h1>';
textElement.style.color = 'red'; // Error!
</script>
innerHTML
操作会破坏对原有 DOM 结构的引用。上面的代码中,textElement
在 innerHTML
修改后失效,继续使用会报错。
解决引用失效的方法
可以先使用 innerHTML
修改内容,然后重新获取元素引用:
const wrapperElement = document.getElementsByClassName('wrapper')[0];
wrapperElement.innerHTML += '<h1>World</h1>';
const textElement = document.getElementsByTagName('span')[0];
textElement.style.color = 'red'; // OK
element.outerHTML
与 innerHTML
类似,outerHTML
可以替换元素本身及其所有子节点:
wrapperElement.outerHTML = '<div>Replaced</div>';
设置 innerHTML 的原理
执行 element.innerHTML = '<h1>title</h1>'
时,大致经历以下步骤:
- 浏览器解析
'<h1>title</h1>'
字符串为 HTML 文档结构。 - 使用
DocumentFragment
将解析后的 HTML 转换为 DOM 节点。 - 替换元素原有的所有子节点。
由于涉及 HTML 解析和大量 DOM 操作,innerHTML
的执行速度较慢,应谨慎使用。
安全问题
现代浏览器出于安全考虑,会阻止通过 innerHTML
插入的 <script>
标签执行:
const content = '123';
wrapperElement.innerHTML = '<script>alert("Hi")</script>';
wrapperElement.innerHTML = content; // 不会弹出 alert
然而,通过其他方式插入的恶意代码仍可能带来安全隐患:
const content = '<img src="x" onerror="alert(\'Hacked!\')" />';
wrapperElement.innerHTML = content; // 会执行 alert
因此,避免使用 innerHTML
插入不可信的内容,以防范 XSS 攻击。
使用建议
插入纯文本内容时,建议使用 Node.textContent
代替 innerHTML
。textContent
仅插入文本内容,不解析 HTML 标签,执行效率更高,且更安全:
wrapperElement.textContent = 'Hello <b>World</b>!';
需要动态创建 DOM 元素时,建议使用 document.createElement
等底层 API 代替字符串拼接:
const divElement = document.createElement('div');
divElement.innerHTML = '<h1>Hello World</h1>';
document.body.appendChild(divElement);
HTMLElement.innerText
innerText
用于设置或获取元素的渲染文本内容。
与 textContent 的区别
textContent
获取元素的所有文本内容,包括 <script>
、<style>
等特殊标签中的内容。
innerText
仅获取用户可见的内容,受 CSS 样式影响。此外,读取 innerText
时,浏览器需重新计算渲染结果,性能较差。
<div class="wrapper">
<h1>标题</h1>
<p class="content">
<style>
.content {
color: orange;
}
</style>
可见内容
<br />
可见内容
<span style="display: none;">不可见内容</span>
</p>
</div>
<script>
const wrapper = document.querySelector('.wrapper');
console.log(wrapper.innerText);
// 输出:
// 标题
// 可见内容
// 可见内容
console.log(wrapper.textContent);
// 输出:
// 标题
//
// .content { color: orange; }
//
// 可见内容
//
// 可见内容
// 不可见内容
</script>