Handles
簡介
Playwright 可以在頁面 DOM 元素或頁面內部的任何其他物件建立 handles。這些 handles 存在於 Playwright 程序中,而實際的物件則存在於瀏覽器中。Handles 有兩種型別
- JSHandle,用於參照頁面中的任何 JavaScript 物件
- ElementHandle,用於參照頁面中的 DOM 元素,它具有額外的方法,可讓您對元素執行動作並斷言其屬性。
由於頁面中的任何 DOM 元素也是 JavaScript 物件,因此任何 ElementHandle 也都是 JSHandle。
Handles 用於對頁面中那些實際的物件執行操作。您可以對 handle 進行評估、取得 handle 屬性、將 handle 作為評估參數傳遞、將頁面物件序列化為 JSON 等。請參閱 JSHandle 類別 API 以了解這些方法。
API 參考
以下是取得 JSHandle 最簡單的方式。
- 同步
- 非同步
js_handle = page.evaluate_handle('window')
# Use jsHandle for evaluations.
js_handle = await page.evaluate_handle('window')
# Use jsHandle for evaluations.
元素 Handles
不建議使用 ElementHandle,請改用 Locator 物件和網頁優先的斷言。
當需要 ElementHandle 時,建議使用 page.wait_for_selector() 或 frame.wait_for_selector() 方法來取得。這些 API 會等待元素附加並可見。
- 同步
- 非同步
# Get the element handle
element_handle = page.wait_for_selector('#box')
# Assert bounding box for the element
bounding_box = element_handle.bounding_box()
assert bounding_box.width == 100
# Assert attribute for the element
class_names = element_handle.get_attribute('class')
assert 'highlighted' in class_names
# Get the element handle
element_handle = page.wait_for_selector('#box')
# Assert bounding box for the element
bounding_box = await element_handle.bounding_box()
assert bounding_box.width == 100
# Assert attribute for the element
class_names = await element_handle.get_attribute('class')
assert 'highlighted' in class_names
將 Handles 作為參數
Handles 可以傳遞到 page.evaluate() 和類似的方法中。以下程式碼片段會在頁面中建立一個新的陣列,使用資料初始化它,並將此陣列的 handle 傳回 Playwright。然後,它會在後續的評估中使用該 handle
- 同步
- 非同步
# Create new array in page.
my_array_handle = page.evaluate_handle("""() => {
window.myArray = [1];
return myArray;
}""")
# Get current length of the array.
length = page.evaluate("a => a.length", my_array_handle)
# Add one more element to the array using the handle
page.evaluate("(arg) => arg.myArray.push(arg.newElement)", {
'myArray': my_array_handle,
'newElement': 2
})
# Release the object when it's no longer needed.
my_array_handle.dispose()
# Create new array in page.
my_array_handle = await page.evaluate_handle("""() => {
window.myArray = [1];
return myArray;
}""")
# Get current length of the array.
length = await page.evaluate("a => a.length", my_array_handle)
# Add one more element to the array using the handle
await page.evaluate("(arg) => arg.myArray.push(arg.newElement)", {
'myArray': my_array_handle,
'newElement': 2
})
# Release the object when it's no longer needed.
await my_array_handle.dispose()
Handle 生命週期
可以使用頁面方法(例如 page.evaluate_handle()、page.query_selector() 或 page.query_selector_all())或其框架對應方法 frame.evaluate_handle()、frame.query_selector() 或 frame.query_selector_all() 來取得 handles。一旦建立,handles 將會保留來自 垃圾回收 的物件,除非頁面導航或 handle 透過 js_handle.dispose() 方法手動處置。
API 參考
- JSHandle
- ElementHandle
- element_handle.bounding_box()
- element_handle.get_attribute()
- element_handle.inner_text()
- element_handle.inner_html()
- element_handle.text_content()
- js_handle.evaluate()
- page.evaluate_handle()
- page.query_selector()
- page.query_selector_all()
Locator 與 ElementHandle
我們僅建議在極少數情況下使用 ElementHandle,即當您需要在靜態頁面上執行廣泛的 DOM 遍歷時。對於所有使用者動作和斷言,請改用 locator。
Locator 和 ElementHandle 之間的區別在於,後者指向特定的元素,而 Locator 則捕捉了如何檢索該元素的邏輯。
在以下範例中,handle 指向頁面上特定的 DOM 元素。如果該元素變更文字,或被 React 用於呈現完全不同的元件,handle 仍然指向該非常陳舊的 DOM 元素。這可能會導致意外的行為。
- 同步
- 非同步
handle = page.query_selector("text=Submit")
handle.hover()
handle.click()
handle = await page.query_selector("text=Submit")
await handle.hover()
await handle.click()
使用 locator,每次使用 locator 時,都會使用選取器在頁面中找到最新的 DOM 元素。因此,在以下程式碼片段中,底層的 DOM 元素將被找到兩次。
- 同步
- 非同步
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()