处理不是脚本或样式元素的文本节点
Posted
技术标签:
【中文标题】处理不是脚本或样式元素的文本节点【英文标题】:Handle Text Nodes That Are Not Script or Style Elements 【发布时间】:2019-07-03 06:44:56 【问题描述】:我有这个处理所有文本节点的基本代码:
function walk (node)
if (node.nodeType == '3')
handleText (node)
node = node.firstChild
while (node)
walk (node)
node = node.nextSibling
不幸的是,这会处理所有文本节点,包括我不想要的<script>
和<style>
等元素。我将我的代码更新为以下内容以忽略这些特定元素:
function walk (node)
if (node.nodeType == '3' && node.tagName != 'SCRIPT' && node.tagName != 'STYLE')
handleText (node)
node = node.firstChild
while (node)
walk (node)
node = node.nextSibling
但是,这不起作用。我做错了什么?
【问题讨论】:
【参考方案1】:带有nodeType
的3
的node
将是一个文本节点。由于听起来您想排除作为 script
或 style
标签的 children 的文本节点的遍历,因此您应该将测试放在别处 - 如果 tagName
不是,则仅 walk(node)
SCRIPT
OR STYLE
,这样父标签<script>
/<style>
就不会被迭代:
function walk (node)
if (node.nodeType === 3)
handleText (node);
node = node.firstChild;
while (node)
const tagName = node;
if (tagName !== 'SCRIPT' && tagName !== 'STYLE')
walk (node);
node = node.nextSibling;
(还要注意nodeType
的计算结果为整数,因此您可以改用严格相等比较===
)
为避免while
循环和重新分配,您可以考虑改用forEach
:
function walk (node)
if (node.nodeType === 3)
handleText (node);
return;
Array.prototype.forEach.call(
node.childNodes,
(childNode) =>
const tagName = childNode;
if (tagName !== 'SCRIPT' && tagName !== 'STYLE')
walk (child);
);
【讨论】:
感谢您的帮助!我注意到您提供了一个替代示例来“避免while
循环和重新分配”。使用“while
循环和重新分配”不好吗?
这有点基于意见,但可以说是的。当没有重新分配任何内容时,代码更易于阅读 - 在循环的 end 手动重新分配 outer 变量很难一目了然。在大多数情况下,通常可以更好地避免循环;数组方法提供更多抽象,可组合,不需要手动迭代或重新分配。【参考方案2】:
标签检查应该在父节点上:
function walk(node)
if (node.nodeType == 3 && !/SCRIPT|STYLE/.test(node.parentNode.tagName)) handleText(node);
for (node = node.firstChild; node; node = node.nextSibling) walk(node)
【讨论】:
以上是关于处理不是脚本或样式元素的文本节点的主要内容,如果未能解决你的问题,请参考以下文章