Open lmk123 opened 2 years ago
在今天之前,我一直认为 textContent 与 innerText 是等价的,只不过前者是标准的,后者是非标准的。所以,我一直以来都使用 textContent 读取一个元素的文本内容。
textContent
innerText
但是,今天遇到了一个 bug 让我发现,这两者是有区别的,而且,某些情况下,innerText 更适用一些。
这个 bug 出在划词翻译当中,先看图:
这段英文出自 https://github.com/websockets/ws,图中的英文段落是一个 p 元素,划词翻译的全文翻译功能会读取这个元素的 textContent 并将翻译结果显示在下方。这个 bug 就在于,我发现翻译结果不太准确,而且有一些地方有不易察觉的空格,注意图中的“该扩展使 客户端”,其中“使”和“客”中间有一个空格。
p
在经过一番调试,我发现 p.textContent 读取出来的英文文本 which enables the client 的 enables 和 the 中间的不是空格,而是一个换行符 \n!
p.textContent
which enables the client
\n
从视觉上看这应该是一个空格,但 textContent 却读取出来了换行符,导致划词翻译将一句话拆分成了两句话进行翻译,所以翻译结果就不准确了。
我谷歌了一下 textContent 为什么会有换行符,但得到的搜索结果都讲的是如何在 textContent 里加换行符,只有一条链接引起了我的注意:What's Best: innerText vs. textContent
What's Best: innerText vs. textContent
抱着试一试的想法,我试了一下 p.innerText,它返回的就是正常的空格——这一刻我被惊讶到了:原来 textCotent 和 innerText 不是等价的!
p.innerText
textCotent
为了知道为什么 innerText 的内容里不包含空格,我查了一下这两者的不同点。我主要看了以下两个链接:
总结如下:
<style>
<script>
<span style="display:none">
再回到文章开头的那个段落,为什么视觉上的空格其实是一个换行符?我在 README.md 里找到了答案。
在 Markdown 里,这里确实是有换行的:
.....................which enables the client........................
然后这个段落被渲染成 HTML 之后是这样的:
<p> .....................which enables the client........................ </p>
浏览器在渲染这个 p 元素时,会把换行符显示成空格,这也就导致了视觉上的空格其实是换行符的问题。
由于 innerText 的性能问题,前面提到的文章建议使用 textContent 替代 innerText。但是,在划词翻译的全文翻译场景下,用 innerText 更合适——因为它不会读取出来不可见的文本。
之前就有用户反馈过这个问题:全文翻译会出现额外的字符翻译,这个问题其实就是不可见的元素被 textContent 读取出来然后也翻译了。我本来还打算自己写一个方法用于去掉不可见元素,但现在直接换成 innerText 就可以了。至于性能方面,实际使用起来完全没觉得比 textContent 慢。
最后,还有一个需要注意的点:如果元素本身就是一个不可见元素,那么 innerText 和 textContent 的内容是一样的。
在今天之前,我一直认为
textContent
与innerText
是等价的,只不过前者是标准的,后者是非标准的。所以,我一直以来都使用textContent
读取一个元素的文本内容。但是,今天遇到了一个 bug 让我发现,这两者是有区别的,而且,某些情况下,
innerText
更适用一些。先说说 bug
这个 bug 出在划词翻译当中,先看图:
这段英文出自 https://github.com/websockets/ws,图中的英文段落是一个
p
元素,划词翻译的全文翻译功能会读取这个元素的textContent
并将翻译结果显示在下方。这个 bug 就在于,我发现翻译结果不太准确,而且有一些地方有不易察觉的空格,注意图中的“该扩展使 客户端”,其中“使”和“客”中间有一个空格。在经过一番调试,我发现
p.textContent
读取出来的英文文本which enables the client
的 enables 和 the 中间的不是空格,而是一个换行符\n
!从视觉上看这应该是一个空格,但
textContent
却读取出来了换行符,导致划词翻译将一句话拆分成了两句话进行翻译,所以翻译结果就不准确了。我谷歌了一下 textContent 为什么会有换行符,但得到的搜索结果都讲的是如何在 textContent 里加换行符,只有一条链接引起了我的注意:
What's Best: innerText vs. textContent
抱着试一试的想法,我试了一下
p.innerText
,它返回的就是正常的空格——这一刻我被惊讶到了:原来textCotent
和innerText
不是等价的!innerText
与textContent
的不同之处为了知道为什么
innerText
的内容里不包含空格,我查了一下这两者的不同点。我主要看了以下两个链接:总结如下:
textContent
会把所有子元素的文本连接起来并返回,但是innerText
会返回一个“人类可见 & 可读”的文本,它不会返回不可见元素的文本(例如<style>
、<script>
、<span style="display:none">
),就好像你用鼠标选中这段文本后再 Ctrl + C 得到的文本。innerText
属性时会为了计算 CSS 而造成一次重绘(reflow),所以它的性能比 textContent 低。回到开头的英文段落
再回到文章开头的那个段落,为什么视觉上的空格其实是一个换行符?我在 README.md 里找到了答案。
在 Markdown 里,这里确实是有换行的:
然后这个段落被渲染成 HTML 之后是这样的:
浏览器在渲染这个
p
元素时,会把换行符显示成空格,这也就导致了视觉上的空格其实是换行符的问题。innerText
更适合划词翻译的全文翻译场景由于
innerText
的性能问题,前面提到的文章建议使用textContent
替代innerText
。但是,在划词翻译的全文翻译场景下,用innerText
更合适——因为它不会读取出来不可见的文本。之前就有用户反馈过这个问题:全文翻译会出现额外的字符翻译,这个问题其实就是不可见的元素被 textContent 读取出来然后也翻译了。我本来还打算自己写一个方法用于去掉不可见元素,但现在直接换成 innerText 就可以了。至于性能方面,实际使用起来完全没觉得比
textContent
慢。最后,还有一个需要注意的点:如果元素本身就是一个不可见元素,那么
innerText
和textContent
的内容是一样的。