如何在Jest中从多行字符串构建HTML DOM并访问子元素?
问题
我正尝试在Jest中从**多行字符串(multiline string)**构建HTML DOM,以测试浏览器扩展。但当我尝试访问DOM的子元素时,返回的是文本而非DOM节点。
已尝试方案
我试过多种方法,但都存在相同问题:
const html = ` <div id="id1"> <p id="id2"> <span id="id3">Hello World</span> </p> </div> ` const template = document.createElement('template') template.innerHTML = html.trim() console.log(template.content.firstChild?.firstChild) // Text {Symbol(impl): TextImpl} const htmlParser = new DOMParser() const parsed = htmlParser.parseFromString(html.trim(), 'text/html') console.log(parsed.body.firstChild?.firstChild) // Text {Symbol(impl): TextImpl} const dom = new JSDOM(html.trim()) console.log(dom.window.document.body.firstChild?.firstChild) // Text {Symbol(impl): TextImpl}
(已在jest.config.js中配置testEnvironment: "jsdom")
疑问
是否有方法能在Jest中正确从多行字符串构建HTML DOM并访问其子元素?
解决方案
问题出在多行字符串里的换行和缩进会被解析成空白文本节点,导致firstChild返回的不是你期望的元素节点。以下两种方法可以解决:
方法1:清理字符串中的空白
在赋值给innerHTML前,移除字符串里的换行和多余空白字符:
const html = ` <div id="id1"> <p id="id2"> <span id="id3">Hello World</span> </p> </div> `.replace(/\n\s+/g, '') // 匹配换行及后续的空白并移除 const template = document.createElement('template') template.innerHTML = html console.log(template.content.firstChild?.firstChild) // <p id="id2">...</p>
方法2:使用元素专属的DOM访问方法
直接用firstElementChild替代firstChild,它会跳过空白文本节点,只返回第一个元素节点:
// Template方式 const template = document.createElement('template') template.innerHTML = html.trim() console.log(template.content.firstElementChild?.firstElementChild) // <p id="id2">...</p> // DOMParser方式 const parsed = new DOMParser().parseFromString(html.trim(), 'text/html') console.log(parsed.body.firstElementChild?.firstElementChild) // JSDOM方式 const dom = new JSDOM(html.trim()) console.log(dom.window.document.body.firstElementChild?.firstElementChild)
额外提示
如果需要遍历所有子元素,用children属性(仅包含元素节点)替代childNodes(包含所有类型节点),也能避免空白文本的干扰。
内容的提问来源于stack exchange,提问作者baruchiro
相关产品推荐
相关产品推荐

