Yihui’s Blog

jsdom

在现代的Web开发中,JavaScript是一种不可或缺的编程语言。它使得网页更加交互和动态,并且为开发人员提供了丰富的工具和库来简化开发过程。其中一个非常有用的工具是jsdom,它是一个在Node.js环境中模拟浏览器DOM的JavaScript库。

jsdom允许开发人员在服务器端使用类似于浏览器的API,如document对象、querySelector和innerHTML等。这意味着我们可以在服务器上执行JavaScript代码,操作和操纵DOM元素,从而实现一些在浏览器环境下才能完成的任务。

使用jsdom的第一步是安装它。在命令行中运行以下命令即可:

npm install jsdom

安装完成后,我们可以在我们的代码中引入jsdom模块:

const { JSDOM } = require("jsdom");

接下来,我们可以使用JSDOM构造函数来创建一个虚拟的DOM环境:

const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);

现在,我们可以通过访问dom.window.document来获取虚拟DOM的根元素,就像在浏览器中一样:

const document = dom.window.document;

我们可以使用document对象的各种方法和属性来操作虚拟DOM。例如,我们可以使用querySelector来选择元素,使用innerHTML来设置元素的内容,使用addEventListener来添加事件监听器等等。

const element = document.querySelector("p");
element.innerHTML = "Hello jsdom!";
element.addEventListener("click", () => {
  console.log("Element clicked!");
});

除了模拟DOM之外,jsdom还提供了其他一些功能。例如,我们可以使用jsdom来执行JavaScript代码,从而测试我们的代码在不同环境下的行为。我们还可以使用jsdom来解析和操作HTML文档,以及执行一些与浏览器相关的任务。

总结一下,jsdom是一个非常有用的JavaScript库,它允许我们在服务器端使用类似于浏览器的API来操作和操纵DOM。它为我们提供了一种在非浏览器环境下开发和测试JavaScript代码的方式。无论是构建自动化测试工具还是进行Web爬虫开发,jsdom都是一个非常有用的工具。

希望这篇博客能够帮助你了解什么是jsdom以及如何使用它。无论你是初学者还是有经验的开发人员,掌握jsdom都将对你的开发工作带来很大的帮助。开始使用jsdom,发挥它的强大功能,提升你的Web开发技能吧!

对象API

JSDOM是一个用于在Node.js环境中模拟浏览器DOM的库。它提供了一组API,用于操作和处理虚拟DOM。

以下是JSDOM对象API的一些总结:

  1. 属性:

    • window:获取创建的Window对象。
    • virtualConsole:反映传入的选项或默认选项中的虚拟控制台。
    • cookieJar:反映传入的选项或默认选项中的cookieJar。
  2. 使用serialize()方法序列化文档:

    • serialize()方法将返回文档的HTML序列化字符串,包括文档类型。
    • 示例:dom.serialize() === “hello”;
  3. 使用nodeLocation(node)方法获取节点的源位置:

    • nodeLocation()方法将返回节点在源文档中的位置信息。
    • 仅在设置了includeNodeLocations选项时才有效,默认情况下为关闭状态。
  4. 使用getInternalVMContext()方法与Node.js的vm模块进行交互:

    • getInternalVMContext()方法可用于获取适用于vm API的上下文化全局对象。
    • 适用于高级用例,如预编译脚本并多次运行。
  5. 使用reconfigure(settings)方法重新配置JSDOM:

    • reconfigure()方法可用于重新配置JSDOM实例。
    • 可以用于重写window.top属性和修改JSDOM的URL。

这些API提供了在JSDOM中操作和处理虚拟DOM的灵活性和功能。使用这些API,可以模拟和测试在浏览器环境中运行的代码,而无需实际打开浏览器。

简便的API

fromURL()方法可以通过URL地址构建jsdom实例,并能够处理重定向。fromFile()方法可以通过文件名构建jsdom实例,文件名相对于当前工作目录。另外,还有一个fragment()方法可以从给定的字符串创建一个DocumentFragment对象,用于简单的HTML解析和DOM操作。需要注意的是,DocumentFragment对象不具有关联的浏览上下文,因此资源不会加载。

fromURL()方法的参数和JSDOM构造函数类似,但有一些限制,例如不能提供url和contentType选项,而referrer选项会作为初始请求的HTTP Referer请求头。返回的promise对象将在URL有效且请求成功时被解析为一个JSDOM实例。

fromFile()方法类似于fromURL()方法,但是通过文件名来构建jsdom实例。返回的promise对象将在给定的文件能够打开时被解析为一个JSDOM实例。

fragment()方法用于简单的HTML解析和DOM操作。它可以通过给定的字符串创建一个DocumentFragment对象。需要注意的是,DocumentFragment对象没有关联的浏览上下文,因此资源不会加载。所有调用fragment()方法返回的DocumentFragment对象共享相同的模板所有者Document。

总之,jsdom提供了方便的API来构建jsdom实例,可以通过URL地址或文件名创建实例,还可以通过fragment()方法创建简单的HTML解析对象。

其他特性

总结:

  1. Canvas支持:jsdom支持使用canvas包来扩展任何<canvas>元素的canvas API。为了实现这一功能,你需要将canvas作为jsdom项目的依赖项之一。如果jsdom能够找到canvas包,它将使用它,但如果没有找到,<canvas>元素将表现得像<div>元素。自jsdom v13起,需要使用2.x版本的canvas;不再支持1.x版本。

  2. 编码嗅探:除了提供字符串之外,JSDOM构造函数还可以提供二进制数据,例如Node.js的Buffer或标准的JavaScript二进制数据类型,如ArrayBuffer、Uint8Array、DataView等。当这样做时,jsdom将从提供的字节中嗅探编码,扫描< meta charset>标签,就像浏览器一样。

如果提供的contentType选项包含charset参数,该编码将覆盖嗅探到的编码,除非存在UTF-8或UTF-16的BOM,在这种情况下,BOM将优先。这与浏览器的行为类似。

这种编码嗅探也适用于JSDOM.fromFile()和JSDOM.fromURL()。在后一种情况下,与响应一起发送的任何Content-Type标头将优先,与构造函数的contentType选项相同。

请注意,在许多情况下,以这种方式提供字节可能比提供字符串更好。例如,如果尝试使用Node.js的buffer.toString(“utf-8”) API,Node.js不会删除任何前导BOM。然后,如果将此字符串传递给jsdom,它将逐字解释它,保留BOM。但是,jsdom的二进制数据解码代码将删除前导BOM,就像浏览器一样;在这种情况下,直接提供buffer将得到所需的结果。

  1. 关闭jsdom:jsdom中的定时器(由window.setTimeout()或window.setInterval()设置)将在未来的时间在window的上下文中执行代码。由于没有办法在不保持进程活动的情况下执行未来的代码,未完成的jsdom定时器将保持Node.js进程活动。同样,由于没有办法在不保持对象活动的情况下在对象的上下文中执行代码,未完成的jsdom定时器将阻止垃圾回收窗口。

如果你想确保关闭jsdom窗口,请使用window.close(),它将终止所有运行中的定时器(并且还会删除window和document上的任何事件侦听器)。

  1. 使用Chrome DevTools调试DOM:在Node.js中,你可以使用Chrome DevTools调试程序。请参阅官方文档以了解如何入门。

默认情况下,jsdom元素在控制台中以普通的JS对象格式显示。为了更容易调试,你可以使用jsdom-devtools-formatter,它可以让你像真正的DOM元素一样检查它们。

Maintained by · YihuiEdit on GitHub