ハンドル
はじめに
Playwright は、ページの DOM 要素やページ内の他のオブジェクトへのハンドルを作成できます。これらのハンドルは Playwright プロセス内に存在しますが、実際のオブジェクトはブラウザ内に存在します。ハンドルには2つのタイプがあります。
- JSHandle: ページ内の任意の JavaScript オブジェクトを参照するため
- ElementHandle: ページ内の DOM 要素を参照するため。要素に対してアクションを実行したり、そのプロパティをアサートしたりするための追加のメソッドがあります。
ページ内の任意の DOM 要素は JavaScript オブジェクトでもあるため、任意の ElementHandle は JSHandle でもあります。
ハンドルは、ページ内の実際のオブジェクトに対して操作を実行するために使用されます。ハンドルを評価したり、ハンドルのプロパティを取得したり、ハンドルを評価パラメータとして渡したり、ページオブジェクトを JSON にシリアル化したりできます。これらのメソッドについては、JSHandle クラスの API を参照してください。
API リファレンス
JSHandle を取得する最も簡単な方法を以下に示します。
var jsHandle = await page.EvaluateHandleAsync("window");
// Use jsHandle for evaluations.
要素ハンドル
ElementHandle の使用は非推奨です。Locator オブジェクトと Webファーストのアサーションを使用してください。
ElementHandle が必要な場合は、Page.WaitForSelectorAsync() または Frame.WaitForSelectorAsync() メソッドで取得することをお勧めします。これらの API は、要素がアタッチされ、表示されるのを待ちます。
// Get the element handle
var jsHandle = await page.WaitForSelectorAsync("#box");
var elementHandle = jsHandle as ElementHandle;
// Assert bounding box for the element
var boundingBox = await elementHandle.BoundingBoxAsync();
Assert.AreEqual(100, boundingBox.Width);
// Assert attribute for the element
var classNames = await elementHandle.GetAttributeAsync("class");
Assert.True(classNames.Contains("highlighted"));
パラメータとしてのハンドル
ハンドルは、Page.EvaluateAsync() や類似のメソッドに渡すことができます。以下のスニペットは、ページ内に新しい配列を作成し、データで初期化し、この配列へのハンドルを Playwright に返します。その後、後続の評価でハンドルを使用します。
// Create new array in page.
var myArrayHandle = await page.EvaluateHandleAsync(@"() => {
window.myArray = [1];
return myArray;
}");
// Get the length of the array.
var length = await page.EvaluateAsync<int>("a => a.length", myArrayHandle);
// Add one more element to the array using the handle
await page.EvaluateAsync("arg => arg.myArray.add(arg.newElement)",
new { myArray = myArrayHandle, newElement = 2 });
// Release the object when it is no longer needed.
await myArrayHandle.DisposeAsync();
ハンドルのライフサイクル
ハンドルは、Page.EvaluateHandleAsync()、Page.QuerySelectorAsync()、Page.QuerySelectorAllAsync() などのページメソッド、またはそれに対応するフレームメソッド Frame.EvaluateHandleAsync()、Frame.QuerySelectorAsync()、Frame.QuerySelectorAllAsync() を使用して取得できます。一度作成されたハンドルは、ページがナビゲートされるか、JsHandle.DisposeAsync() メソッドを介して手動で破棄されない限り、ガベージコレクションからオブジェクトを保持します。
API リファレンス
- JSHandle
- ElementHandle
- ElementHandle.BoundingBoxAsync()
- ElementHandle.GetAttributeAsync()
- ElementHandle.InnerTextAsync()
- ElementHandle.InnerHTMLAsync()
- ElementHandle.TextContentAsync()
- JsHandle.EvaluateAsync()
- Page.EvaluateHandleAsync()
- Page.QuerySelectorAsync()
- Page.QuerySelectorAllAsync()
ロケーターと要素ハンドル
静的なページで広範な DOM 走査を実行する必要がある稀なケースでのみ、ElementHandle の使用をお勧めします。すべてのユーザーアクションとアサーションには、代わりにロケーターを使用してください。
ロケーターと要素ハンドルの違いは、後者が特定の要素を指すのに対し、ロケーターはその要素を取得する方法のロジックをキャプチャすることです。
以下の例では、ハンドルはページの特定の DOM 要素を指しています。その要素のテキストが変更されたり、React によってまったく異なるコンポーネントがレンダリングされたりしても、ハンドルはその古い DOM 要素を指し続けます。これは予期せぬ動作につながる可能性があります。
var handle = await page.QuerySelectorAsync("text=Submit");
await handle.HoverAsync();
await handle.ClickAsync();
ロケーターを使用すると、ロケーターが使用されるたびに、セレクターを使用してページ内の最新の DOM 要素が特定されます。したがって、以下のスニペットでは、基になる DOM 要素が2回特定されます。
var locator = page.GetByText("Submit");
await locator.HoverAsync();
await locator.ClickAsync();