跳到主要内容

句柄

简介

Playwright 可以为页面 DOM 元素或页面内的任何其他对象创建句柄。这些句柄存在于 Playwright 进程中,而实际对象存在于浏览器中。有两种类型的句柄

  • JSHandle 用于引用页面中的任何 JavaScript 对象
  • ElementHandle 用于引用页面中的 DOM 元素,它具有额外的方法,允许对元素执行操作并断言其属性。

由于页面中的任何 DOM 元素也是一个 JavaScript 对象,因此任何 ElementHandle 也是一个 JSHandle

句柄用于对页面中的那些实际对象执行操作。您可以在句柄上进行评估,获取句柄属性,将句柄作为评估参数传递,将页面对象序列化为 JSON 等。请参阅 JSHandle 类 API 以了解这些方法。

API 参考

以下是获取 JSHandle 的最简单方法。

const jsHandle = await page.evaluateHandle('window');
// Use jsHandle for evaluations.

元素句柄

不推荐使用

不建议使用 ElementHandle,请使用 Locator 对象和 web-first 断言来代替。

当需要 ElementHandle 时,建议使用 page.waitForSelector()frame.waitForSelector() 方法来获取它。这些 API 会等待元素被附加和可见。

// Get the element handle
const elementHandle = page.waitForSelector('#box');

// Assert bounding box for the element
const boundingBox = await elementHandle.boundingBox();
expect(boundingBox.width).toBe(100);

// Assert attribute for the element
const classNames = await elementHandle.getAttribute('class');
expect(classNames.includes('highlighted')).toBeTruthy();

句柄作为参数

句柄可以传递到 page.evaluate() 和类似的方法中。以下代码片段在页面中创建一个新数组,使用数据初始化它,并将指向此数组的句柄返回到 Playwright 中。然后,它在后续评估中使用该句柄

// Create new array in page.
const myArrayHandle = await page.evaluateHandle(() => {
window.myArray = [1];
return myArray;
});

// Get the length of the array.
const length = await page.evaluate(a => a.length, myArrayHandle);

// Add one more element to the array using the handle
await page.evaluate(arg => arg.myArray.push(arg.newElement), {
myArray: myArrayHandle,
newElement: 2
});

// Release the object when it's no longer needed.
await myArrayHandle.dispose();

句柄生命周期

可以使用页面方法(如 page.evaluateHandle()page.$()page.$$())或其 frame 对应方法(frame.evaluateHandle()frame.$()frame.$$())获取句柄。一旦创建,句柄将保留来自 垃圾回收 的对象,除非页面导航或通过 jsHandle.dispose() 方法手动释放句柄。

API 参考

Locator vs ElementHandle

注意

我们只建议在极少数情况下使用 ElementHandle,即当您需要在静态页面上执行广泛的 DOM 遍历时。对于所有用户操作和断言,请改用 locator。

LocatorElementHandle 之间的区别在于,后者指向特定的元素,而 Locator 捕获了如何检索该元素的逻辑。

在下面的示例中,handle 指向页面上的特定 DOM 元素。如果该元素更改了文本或被 React 用于渲染完全不同的组件,则 handle 仍然指向那个非常陈旧的 DOM 元素。这可能会导致意外的行为。

const handle = await page.$('text=Submit');
// ...
await handle.hover();
await handle.click();

使用 locator,每次使用 locator 时,都会在页面中使用选择器定位最新的 DOM 元素。因此,在下面的代码片段中,底层 DOM 元素将被定位两次。

const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();