在打字稿中,我注意到当我将一个复杂的对象放入数组中时,当我尝试从数组访问该对象时,它会丢失其类型,而只是变成对象类型。
例如
let myArray = return await this.browser.evaluate((sel: string) => Array.from(document.querySelectorAll(sel)), selector)
document.querySelectorAll(sel)
返回NodeList<Element>
的{{1}}。 ArrayLike
应该将Array.from
转换为元素数组,但是一旦形成数组,所有的数组元素都会失去其NodeList
类型
我有一个仅接受类型为Element
的参数的函数,但是当我尝试将Element
作为所述函数的参数传递时,出现错误:myArray[0]
< / p>
我已经尝试了很多不同的方法来尝试使数组保持其对象类型,以致难以解释每一个对象。我想知道如何创建Error: Unsupported target type: object
数组,并在以后访问它们而不是通用Element
时继续使它们成为Element
在我完成的测试中,这里还有更多内容
我要转到此页面:https://www.w3schools.com/html/html_tables.asp
而我要传递给评估的选择器是object
,应该与表中出现的6行匹配。
table[id="customers"] tbody tr
运行上面的代码时,这是我在控制台日志中得到的输出:
let test = await this.browser.evaluate((sel: string) =>
Array.from(document.querySelectorAll(sel)), selector)
console.log('testy1: ', test)
console.log('testy2: ', test[0])
console.log('testy3: ', typeof(test[0]))
似乎正确地从页面中获取了元素,因为它正确地返回了6个元素。但也许问题在于返回的对象为空?我不确定。
我认为我的问题可能与以下问题有关:puppeteer page.evaluate querySelectorAll return empty objects
但是该问题的解决方案对我不起作用,因为href不是对象类型testy1: [ {}, {}, {}, {}, {}, {}, {} ]
testy2: {}
testy3: object
的属性
答案 0 :(得分:1)
这里的问题是要传递给page.evaluate
的函数在浏览器上下文内(在浏览器页面内)运行。要将结果从浏览器上下文发送到Node.js环境,需要对结果进行序列化。
在文档中查看page.evaluate
的返回类型:
returns:Promise <Serializable> Promise可解析为
pageFunction
的返回值
这里的Serializable
意味着您的数据将通过JSON.stringify
传递到Node.js环境,并在那里自动为您解析。但是,此过程将删除对象的所有不可序列化的属性。这就是为什么最终会有许多空对象的原因。
要获取页面上元素的句柄,您需要使用page.$
,它会创建一个对象(在Node.js环境中),该对象链接到浏览器上下文中的元素。这些句柄也可以传递给page.evaluate
调用。要查询多个元素,可以使用函数page.$$
。
代码示例
这里是一个示例,该示例首先查询元素,然后将元素句柄传递给评估函数以读取属性。
const elementHandle = await page.$('a');
const result = await page.evaluate(el => el.href, elementHandle);
与TypeScript有关的问题是,在这种情况下TypeScript无法正确预测类型。对于TypeScript编译器,这看起来像一个普通的函数调用,而实际上,该函数将发送到客户端以执行。因此,在这种情况下,您必须自己转换类型,否则Typescript只会假设any
作为参数类型:
const elementHandle = await page.$('a');
const result = await page.evaluate((el: { href: string }) => el.href, elementHandle);
答案 1 :(得分:0)
我在类型定义上遇到了同样的问题,并且Element没有从任何Lib中导出。
要使用el方法获得适当的智能,我用以下示例更改了代码:
发件人:
...
await page.waitForTimeout(3000)
await page.waitForSelector('button[type=submit]')
await page.$eval('button[type=submit]', el => el.click())
await page.waitForNavigation({waitUntil: "load"})
await page.goto(url)
...
对此:
...
await page.waitForTimeout(3000)
await page.waitForSelector('button[type=submit]')
await page.$('button[type=submit]').then(el => {
el.click()
})
await page.waitForNavigation({waitUntil: "load"})
await page.goto(url)
...
puppeteer element intelisense example
PS:我在DefinedType Github https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24419
的定义类型中发现了问题