Page.locator() 是选择元素并与元素交互的推荐方法。为什么它提供的功能比 Page.$() 少?

问题描述 投票:0回答:1

来自 页面互动 |傀儡师:

定位器是选择元素并与其交互的推荐方式。定位器封装了如何选择元素的信息,它们允许 Puppeteer 自动等待元素出现在 DOM 中并处于执行操作的正确状态。您始终使用 page.locator() 或 frame.locator() 函数实例化定位器。如果定位器 API 没有提供您需要的功能,您仍然可以使用较低级别的 API,例如 page.waitForSelector() 或 ElementHandle。

这张表总结了我对

locator()
$()
之间区别的理解:

Page
方法
返校了 等待元素出现在 DOM 中? 需要
await
吗?
输入法
locator()
Locator
是(重试直至成功或超时) 没有 只有
click
hover
scroll
$()
ElementHandle
没有 是的 各种

我有一些问题:

  • 如果
    locator()
    等待元素出现在 DOM 中,那么它不是必须有
    await
    吗?同样,如果
    $()
    不等待,那不是就不需要
    await
    吗?
  • 为什么
    $()
    这种不等待元素出现在 DOM 中的方法比等待元素出现的方法有更多的输入方法?
  • 在幕后,
    locator()
    waitForSelector()
    $()
    的组合吗?
javascript puppeteer
1个回答
0
投票

从根本上来说,对定位器可能存在一些误解。这是一个很好的入门读物:了解剧作家定位器承诺

定位器和

page.$
(以及类似的调用)之间的主要区别是定位器是惰性的,并且在对它们调用操作之前不执行任何操作。调用
page.locator()
(还有
page.getByRole()
page.getByText()
等——这些也是定位器)声明 一个选择策略,稍后可能会调用该策略。没有
await
,因为还没有任何操作,也没有异步 CDP(Chrome Devtools 协议)或浏览器自动化进程间调用。

另一方面,

page.$()
运行立即查询并返回元素句柄。

当你调用

await page.locator("p").click()
时,
.click()
部分是一个连锁动作。考虑:

const elementHandle = await page.$("p");
await elementHandle.click();

使用定位器,您可以将其分成两行:

const locator = page.locator("p");
await locator.click();

在上面的示例中,这种差异可能看起来毫无意义,但是将选择与操作分开有许多微妙而重要的优点:

  • 定位器默认使用严格模式,避免误报和静默失败。

  • 定位器仅对浏览器进行一次 CDP 调用(而不是两次),并在操作的确切时刻查询元素,避免了在 CDP 调用之间页面发生更改的机会。

    相反,

    page.$
    版本会进行两次调用,由于查询和操作是分离的,因此引发了竞争条件。如果元素无效或意外更改,可能会发生难以调试的故障。

  • 定位器版本可以声明一次并轻松重用,声明和使用之间有很多“空间”(就代码和时间而言)。这有利于像POM这样的最佳实践测试方法,并使大型测试更容易维护。

  • 定位器有许多最佳实践、面向用户的别名,例如

    .getByRole()
    ,可以避免使用 CSS 或 XPath 查询页面等反模式。

因此,不鼓励和/或弃用

page.$
和在元素句柄上操作的类似函数。对于几乎所有的意图和目的,标准都是假装它们不存在。它们是从 Puppeteer 继承的遗留结构,但一旦 Playwright 团队创新了当前基于定位器的方法(Puppeteer 已经复制了自己的方法),它们就变得过时了。

© www.soinside.com 2019 - 2024. All rights reserved.