我正在使用jsdom
和jquery
来在Node.js应用程序中抓取静态Web内容。
jsdom
将HTML字符串转换为包含window
属性的DOM树。我发现必须将DOM的window
属性分配给global.window
,否则会出现JQuery错误(说是需要全局窗口对象)。为什么要这样做?
// Create DOM from HTML
const JSDOM = require('jsdom').JSDOM;
const jsDom = new JSDOM('<html>...</html>')
// Set up JQuery
const { window } = jsDom;
const { document } = window;
global.window = window;
const $ = global.jQuery = require('jquery');
// Scrape content
const tbl = $(document)
.find('#table-id')
.find('tr').each(function() {
// Do something with $(this).html()
})
此外,我经常看到这样的情况:const $ = global.jQuery = require('jquery');
为什么global.jQuery
是必需的?
答案 0 :(得分:3)
jQuery期望在浏览器中运行。在浏览器中,window
存在于全局空间中,而jQuery将其用于某些功能。在Node.js中,您的代码在为包含它的文件创建的作用域中运行。即使您不认为它是 module ,Node.js也不会在您的所有const
(和let
)声明中都区分出顶层您的文件声明了范围为文件的变量。因此,const { window } = jsDom;
不会将window
放在全局空间中,并且jQuery无法访问它。
在Node中运行jQuery时,您有两种选择:
执行您的操作:首先将window
暴露到全局空间中,然后加载jQuery。效果很好。
您可以改为执行此操作:
const JSDOM = require('jsdom').JSDOM;
const jsDom = new JSDOM('<html>...</html>');
const { window } = jsDom;
const { document } = window;
const $ = global.jQuery = require("jquery")(window);
您也在询问const $ = global.jQuery = require('jquery');
。以我的经验,大多数依赖jQuery的库(例如jQuery插件)都将其称为jQuery
。他们在这样的IIFE中运行:
(function ($) { // Inside the IIFE, jQuery is bound to $.
}(jQuery)); // jQuery is grabbed from the global space as jQuery.
因此,您希望jQuery
在全局空间中支持依赖它的库。
答案 1 :(得分:0)
您可以这样做:
const jsDom = new JSDOM('<html>...</html>');
const $ = global.jQuery = (require('jquery'))(jsDom.window);