译自freeCodeCamp - innerHTML vs innerText vs textContent - 有什么不同呢?

193 阅读6分钟

推荐先阅读样例, 之后回来看概念更便于理解

完全是纯手工翻译, 翻译不易, 有帮助的话点个赞吧!


innerHTML vs innerText vs textContent – What's the Difference?

原文链接: freeCodeCamp article By Benjamin Semah

在HTML中, innerHTMLinnerText, 和 textContent 是DOM的一些属性, 能够让你读取或更新HTML的内容.

但是它们在包含不同内容时和在处理 HTML 标记上, 都会有不同的行为.

读完本文后, 你将会知道这三种属性有什么不同, 并且明白在什么时候适合使用哪一个?

内容目录

  • 什么是innerHTML属性?
  • 什么是innerText属性?
  • 什么是textContent属性?
  • 怎么使用innerHTML, innerTexttextContent读取内容?
  • 怎么使用innerHTML, innerTexttextContent更新内容?
  • 使用innerHTML的安全问题
  • 总结

首先, 我将解释这三个属性是怎么工作的, 然后你将通过一些用例来学习它们之间的行为有什么不同.

什么是 innerHTML 属性?

当使用 innerHTML 属性时, 它会读取 HTML 标记和该元素的文本内容二者. 这意味着当使用 innerHTML 设置这个元素的内容, 你可以包含 HTML 标签, 此时浏览器可以正确地渲染它们.

但是要注意, 如果你要从用户或者其他不可行来源使用 innerHTML 插入内容的话, 不怀好意的攻击者就会使用 HTML 的 <script> 标签在你的 app 中插入一些危险代码, 待会文章末尾会详细谈到.

什么是 innerText 属性?

这个属性重点是渲染文本内容, 当你使用 innerText 来读取某个元素的内容时, 它会返回文本在屏幕上的显示效果. 它会忽略 HTML 标签, 并且不显示使用 CSS 隐藏了的内容

当你需要考虑样式时, 你应考虑使用 innerText. 调整某个元素的 innerText 意味着浏览器也许会需要调整布局来适配文本大小的改变, 这暗含了一些性能上的调整.

什么是 textContent 属性?

textContent 属性也会忽略所有HTML标签并且只返回它的文本. 与 innerText 属性读取在屏幕上渲染的文本不同的是, textContent只是读取起到标记作用的文本, 意思是它将返回所有文本, 无论是否会在屏幕上渲染.

还有, textContent 只处理原始文本并不考虑样式, 所以在考虑性能而不考虑样式的情况下, textContent 是相对于innerText更高效的选择.

怎么使用 innerHTML, innerTexttextContent 读取内容?

现在, 让我们在进入实操环节, 加深我们对这三种属性的理解.

下面是一个简单的四个选项的导航栏标记, 最后一个文本为 "Pricing" 的元素被隐藏了( display 属性设置成 none ). 让我们用三种属性来看一看 nav 元素会有什么不同吧.

<nav>
  <a>Home</a>
  <a>About</a>
  <a>Contact</a>
  <a style="display: none">Pricing</a>
</nav>

Image一个简单的导航栏

使用 innerHTML 获取内容

// 使用 innerHTML 获取内容
const navElement = document.querySelector('nav')
console.log(navElement.innerHTML)

innerHTML example that includes both markup and textinnerHTML 例子, 标记和文本均包含

innerHTML 属性返回所有内容, 包括 nav 元素里的所有HTML标签及其文本内容

使用 innerText获取内容

    // 使用 innerText 获取内容
    const navElement = document.querySelector('nav')
    console.log(navElement.innerText)

ImageinnerText 例子, 打印出显示在屏幕上的效果

innerText 属性返回渲染在屏幕上的内容, 忽略所有 HTML 标签. 也忽略被隐藏的内容(即 display 属性设置成 none )

使用 textContent 获取内容

    // 使用 `textContent` 获取内容
    const navElement = document.querySelector('nav')
    console.log(navElement.textContent)

ImagetextContent 例子, 打印出标记中的文本包括隐藏的文本👆

textContent 属性返回在HTML标记中的内容. 类似于 innerText , 忽略HTML标签, 但不同的是, textContent 并不考虑样式, 所以会返回 "Pricing" , 就算它被设置成隐藏.

怎么使用 innerHTML, innerTexttextContent 更新内容?

这三种属性均可以用来更新DOM元素的内容. 当更新内容时, 这些属性的使用与读取内容相似.

让我们用一些例子来深入理解吧

使用 innerHTML 更新内容

以下标记包括一个header元素和一个空的 <ul> 元素, 你可以使用 innerHTML 属性来插入某些内容到 <ul>

<h2>Programming languages</h2>
<ul class="languages-list"></ul>
const langListElement = document.querySelector('.languages-list')

// 使用innerHTML设置或更新内容
langListElement.innerHTML = `
  <li>JavaScript</li>
  <li>Python</li>
  <li>PHP</li>
  <li>Ruby</li>
`

Image一个使用 innerHTML 更新内容的例子👆

这些 JavaScript 代码传递HTML列表的字符串给 innerHTML , innerHTML 属性便识别HTML标签并将内容进行对应的排版

不像 innerHTML, innerText 和 textContent 会忽略HTML标签并将所有内容按字符串渲染.

使用 innerText 更新内容

同一个例子, 让我们看看 innerText 属性会怎样更新这个编程语言( Programming languages )的列表

const langListElement = document.querySelector('.languages-list')

langListElement.innerText = `
  <li>JavaScript</li>
  <li>Python</li>
  <li>PHP</li>
  <li>Ruby</li>
`

Image一个使用innerText更新内容的例子👆

注意 innerText 是怎么忽略 HTML 标签并把部分文本打印在屏幕上的. 但是像换行和空格这样的格式仍会保留.

使用 textContent 更新内容

当我们设置或更新内容时, textContent 属性会忽略 HTML 标记并忽略像换行空格这样的格式

const langListElement = document.querySelector('.languages-list')
    langListElement.textContent = `
      <li>JavaScript</li>
      <li>Python</li>
      <li>PHP</li>
      <li>Ruby</li>
    `

Image

因为 textContent 会忽略换行空格这样的格式, 所有文本就会打印在同一行.当你想要原始文本而不考虑文本格式时, textContent 是一个合适的选择.

使用innerHTML的安全问题

因为 innerHTML 处理和解释 HTML 标签, 所以建议只在从可信源插入内容时使用. 或者你有可靠的过滤和验证内容的方法. 浏览器会运行你放在 HTML 标签里的任何 JavaScript 代码. 并且它会打开Cross-Site Scripting (XSS) 的大门, 在那儿攻击者可以向你的网页中注入并运行恶意脚本

看一个例子

    <div id="commentSection"></div>

假设你正在使用以上 div 作为一个你的app里用户评价的容器. 而你使用 innerHTML 来添加评论, 却对评论不做任何验证或过滤

以下是一个最简单的一个用户如何注入并运行一个恶意脚本的例子

const commentSection = document.getElementById('commentSection')

let userComment = `<img src="malicious-script.jpg" onerror="alert('Malicious Script Executed!')"> This is my comment!`;

commentSection.innerHTML = userComment;

Image恶意脚本在innerHTML中通过 <script> 标签运行

这个用户故意给图片一个无效的 src 属性. 这样就会触发 onerror 事件即发出 "Malicious Script Executed!" 的弹窗.

你可以想象攻击者如何利用这个来注入有害的 JavaScript 代码, 很可能窃取用户敏感信息, 操纵网页, 或者进行其他恶意行为

结论

你可以使用这三个属性 innerHTMLinnerText, 和 textContent 来操控DOM元素的内容.但是它们的使用方法各不相同, 了解了其中的区别可以让你做出正确的使用选择.

innerHTMl 属性可以识别 HTML 标签并根据标签渲染内容, 而 textContent 忽略 HTML 标签并只把内容看作文本. 你又学了 innerHTML 可能带来安全隐患, 所以需要谨慎使用.

当然, innerText 读取的内容和它在屏幕上出现一样, 并忽略隐藏的内容, 保留原有格式. 但是 textContent 读取的内容和它出现在标记中的一样, 所以它会读取隐藏内容, 但是会忽略你用来设置内容的格式例如换行和空格.

感谢阅读, 编码愉快!