JSdom 和伪类

问题描述 投票:0回答:1

我正在使用 Node 和 jsdom 进行一些抓取。我有:

const fragments = await document.querySelectorAll("div[data-qa] a:has[span]");

这将导致消息:

unknown pseudo-class selector ':has[span]'

JSdom 可以使用伪类吗?

javascript node.js jsdom
1个回答
0
投票

目前在

JSDOM
中使用伪类:has()有几种方法:

解决方案 1:使用更新的 NWSAPI

为了实现 DOM Selectors API,JSDOM 使用 NWSAPI,需要更新到版本 >= 2.2.5,因为该版本添加了对

:has()
的基本支持。

但是,目前仍然不支持带有嵌套子选择器的更复杂的表达式

:has()

解决方案2:使用polyfill

您可以使用polyfill-pseudoclass-has,它不仅可以与浏览器一起使用,还可以与JSDOM一起使用。

这个polyfill很慢,因为它实现了完全符合DOM API(尤其是NodeList),但是它支持使用复杂的表达式(根据规范),例如:

div[data-qa] a:has(span):has(+ strong > span)

将 Polyfill 注入 JSDOM 的示例(沙箱):

import { JSDOM } from 'jsdom';
import { addTo } from "polyfill-pseudoclass-has";

const customHtml = `
    <h1>Header Example</h1>
    <div data-qa>
        <p>
            <!-- CORRECT -->
            <a href="#!1"><span>Example 1</span></a>
            <strong><span>Custom text 1!</span></strong>
        </p>
        <p>
            <!-- CORRECT -->
            <a href="#!2"><span>Example 2</span></a>
            <strong><span>Custom text 2!</span></strong>
        </p>
        <p>
            <!-- INCORRECT: missing <span> inside <strong> -->
            <a href="#!3"><span>Example 3</span></a>
            <strong>Custom text 3!</strong>
        </p>
    </div>
`;

const {
  window: {document, Element, Document, DocumentFragment},
} = new JSDOM(customHtml);
addTo(Element, Document, DocumentFragment); // inject polyfill

const selector = 'div[data-qa] a:has(span):has(+ strong > span)';
const nodeList = document.querySelectorAll(selector);

console.log(nodeList.length); // => 2

polyfill可以直接使用,无需集成到当前API中:

import { JSDOM } from 'jsdom';
import { SelectorHandler } from "polyfill-pseudoclass-has";

const customHtml = `
  ...
`;

const { window: {document} } = new JSDOM(customHtml);
const selector = 'div[data-qa] a:has(span):has(+ strong > span)';
const selectorHandler = new SelectorHandler('div[data-qa] a:has(span):has(+ strong > span)');
const nodeList = selectorHandler.queryAll(document);
console.log(nodeList.length); // => 2
© www.soinside.com 2019 - 2024. All rights reserved.