jsdom 可以运行在文档的<head>
标记内内联的脚本,但是如何让它运行通过<script src="">
链接到文档头部的脚本?
对于我正在使用的选项:
{
url: url,
resources: 'usable',
runScripts: 'dangerously',
}
// index.js
const request = require('request')
const jsdom = require('jsdom')
const {JSDOM} = jsdom
const url = 'http://localhost:8000'
request(url, (error, response, body) => {
const options = {
url: url,
resources: 'usable',
runScripts: 'dangerously',
}
const dom = new JSDOM(body, options)
console.log(dom.window.document.body.children.length) // Expecting to see `1`
console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
})
// external.js
document.addEventListener('DOMContentLoaded', () => {
document.write('<h1>Hello world!</h1>')
})
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSDOM test</title>
<script src="external.js"></script>
</head>
<body>
</body>
</html>
完整的最小工作示例: https ://github.com/cg433n/jsdom-test
这里的问题是DOMContentLoaded
是一个异步事件。 你在它有机会发生之前就登录了。 您需要等待它触发; 只有这样你的document.write()
才会发生。
像这样的东西应该可以工作:
const dom = new JSDOM(body, options)
dom.window.document.addEventListener('DOMContentLoaded', () => {
// We need to delay one extra turn because we are the first DOMContentLoaded listener,
// but we want to execute this code only after the second DOMContentLoaded listener
// (added by external.js) fires.
setImmediate(() => {
console.log(dom.window.document.body.children.length) // Expecting to see `1`
console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
});
});
我懂了! 你们太棒了——继续努力!
注意:上述演示的 2 个功能存在风险。
request
已折旧。 npm install request
结果:setImmediate
是有风险的。或者,我建议使用fs
从文件中读取和加载 js 代码,请参阅Stackoverflow基于 #3023 中的@EricRicketts ' FS.read()
方法和@Domenic中的addEventListener()
#1914. 我建议的工作演示包括:
fs.readFileSync
将外部 js 作为字符串加载到 html 中这可能会阻止您进行 xhr / API 调用,因此只能部分解决问题。
我无法弄清楚获取网址的方法。
理想情况下,通过 url 工作演示加载 external.js 文件的更新的最小 JSDOM将受到欢迎。 :心:
最有用的评论
这里的问题是
DOMContentLoaded
是一个异步事件。 你在它有机会发生之前就登录了。 您需要等待它触发; 只有这样你的document.write()
才会发生。像这样的东西应该可以工作: