javascript - 如何将 jQuery ':not(:has(*)):not(a *):not(a)' 转换为 TreeWalker 的纯 js?
问题描述
我需要排除一些文本节点。为此我使用
$('body :not(:has(*)):not(script):not(textarea):not(textarea *):not(a *):not(a)')
我使用的功能是:
function findAllTextNodes(n) {
var walker = n.ownerDocument.createTreeWalker(n, NodeFilter.SHOW_TEXT);
var textNodes = [];
while (walker.nextNode())
if (walker.currentNode.parentNode.tagName != 'SCRIPT' &&
walker.currentNode.parentNode.tagName != 'A' && walker.currentNode.parentNode.className != 'to-ignore')
textNodes.push(walker.currentNode);
return textNodes;
}
有没有更好、更易读的方法,我该如何做 ':not(:has(*))' 或 ':not(a *)'?
编辑:没有指向原始帖子的链接,但这里有指向jsfiddle的链接,
我也不希望里面的“the”<a>
被<span>
替换。
解决方案
Document.createTreeWalker构造函数可以包含一个带有过滤函数的 NodeFilter 对象,该函数测试由whatToShow参数选择的每个节点。
对于通过测试的节点,过滤器函数应该返回值NodeFilter.FILTER_ACCEPT。
测试节点时,您可以使用 DOM Element API 中的matches(selectorList)方法和您不想匹配的选择器列表。要么使用简单的列表并否定结果(如示例中所示),要么使用:not(selectorList)伪类。
下面还过滤掉空文本节点和只有空格的节点,因为许多浏览器会插入空文本节点,其中 HTML 源代码在元素标记之间有任何空格(例如<p></p>
,根据周围代码解析时可能有零到三个空文本节点) . 它还将实际文本推送到数组而不是文本节点对象中。
function findTextNodes() {
var walker = document.createTreeWalker(
document.body, // root
NodeFilter.SHOW_TEXT, // nodes to include
{acceptNode: filter} // NodeFilter object
);
var textNodes = [];
while (walker.nextNode()) {
textNodes.push(walker.currentNode.textContent);
}
return textNodes;
}
// NodeFilter function
function filter(node) {
// Ignore any node that matches a selector in the list
// and nodes that are empty or only whitespace
if (!node.parentNode.matches('a, a *, script, textarea, .to-ignore') &&
!/^\s*$/.test(node.textContent)
) {
// If passes test, return accept value
return NodeFilter.FILTER_ACCEPT;
}
}
let textNodes = findTextNodes();
console.log(textNodes.join('\n'));
.to-ignore {
background-color: yellow;
}
a * {
color: green;
}
<p>It's the end of the world as we know it,<br>
and I feel fine</p>
<a>the in a</a>
<br>
<a><span>the in span in a</span></a>
<span class="to-ignore">in to-ignore</span>
过滤器函数将忽略的节点是匹配以下任何选择器的节点:
- a - A 元素
- a * - A 元素的所有后代
- 脚本 - 脚本元素
- textarea - 文本区域元素
- .to-ignore - 具有“to-ignore”类的元素
推荐阅读
- typescript - 错误 TS2339:只读类型上不存在属性
- sql - 从应用脚本查询计算机上的数据库
- javascript - 特定的 React 模型有时不会加载,需要重新渲染
- javascript - 尝试在 React 中实现脚本
- ruby-on-rails - 我可以将 PGOPTIONS 环境变量用于 ruby on rails rails postgresql 会话吗?
- c++ - 我应该担心 SIG35 吗?
- excel - 将值复制/粘贴到 Excel 中的另一个工作表而不激活工作表
- nfs - Onos 3 节点 + Atomix 3 节点集群,NFS 上具有持久性卷
- android - 恢复安装在 Android 模拟器 (Flutter) 上的应用程序的源代码
- java - Eclipse Vert.x:用杰克逊解析 java.time 日期