Handles
Введение
Playwright может создавать ссылки на элементы DOM страницы или любые другие объекты внутри страницы. Эти ссылки существуют в процессе Playwright, тогда как реальные объекты находятся в браузере. Существует два типа ссылок:
- JSHandle для ссылки на любые JavaScript объекты на странице
- ElementHandle для ссылки на DOM элементы на странице, он имеет дополнительные методы, которые позволяют выполнять действия с элементами и проверять их свойства.
Поскольку любой DOM элемент на странице также является JavaScript объектом, любой ElementHandle также является JSHandle.
Ссылки используются для выполнения операций с этими реальными объектами на странице. Вы можете выполнять вычисления на ссылке, получать свойства ссылки, передавать ссылку в качестве параметра вычисления, сериализовать объект страницы в JSON и т.д. См. API класса JSHandle для этих и других методов.
Справочник API
Вот самый простой способ получить JSHandle.
- Sync
- Async
js_handle = page.evaluate_handle('window')
# Используйте jsHandle для вычислений.
js_handle = await page.evaluate_handle('window')
# Используйте jsHandle для вычислений.
Ссылки на элементы
Использование ElementHandle не рекомендуется, вместо этого используйте объекты Locator и утверждения, ориентированные на веб.
Когда требуется ElementHandle, рекомендуется получать его с помощью методов page.wait_for_selector() или frame.wait_for_selector(). Эти API ожидают, пока элемент будет прикреплен и видим.
- Sync
- Async
# Получите ссылку на элемент
element_handle = page.wait_for_selector('#box')
# Проверьте ограничивающий прямоугольник элемента
bounding_box = element_handle.bounding_box()
assert bounding_box.width == 100
# Проверьте атрибут элемента
class_names = element_handle.get_attribute('class')
assert 'highlighted' in class_names
# Получите ссылку на элемент
element_handle = page.wait_for_selector('#box')
# Проверьте ограничивающий прямоугольник элемента
bounding_box = await element_handle.bounding_box()
assert bounding_box.width == 100
# Проверьте атрибут элемента
class_names = await element_handle.get_attribute('class')
assert 'highlighted' in class_names
Ссылки как параметры
Ссылки могут быть переданы в методы page.evaluate() и аналогичные. Следующий фрагмент создает новый массив на странице, инициализирует его данными и возвращает ссылку на этот массив в Playwright. Затем он использует ссылку в последующих вычислениях:
- Sync
- Async
# Создайте новый массив на странице.
my_array_handle = page.evaluate_handle("""() => {
window.myArray = [1];
return myArray;
}""")
# Получите текущую длину массива.
length = page.evaluate("a => a.length", my_array_handle)
# Добавьте еще один элемент в массив, используя ссылку
page.evaluate("(arg) => arg.myArray.push(arg.newElement)", {
'myArray': my_array_handle,
'newElement': 2
})
# Освободите объект, когда он больше не нужен.
my_array_handle.dispose()
# Создайте новый массив на странице.
my_array_handle = await page.evaluate_handle("""() => {
window.myArray = [1];
return myArray;
}""")
# Получите текущую длину массива.
length = await page.evaluate("a => a.length", my_array_handle)
# Добавьте еще один элемент в массив, используя ссылку
await page.evaluate("(arg) => arg.myArray.push(arg.newElement)", {
'myArray': my_array_handle,
'newElement': 2
})
# Освободите объект, когда он больше не нужен.
await my_array_handle.dispose()
Жизненный цикл ссылок
Ссылки могут быть получены с помощью методов страницы, таких как page.evaluate_handle(), page.query_selector() или page.query_selector_all() или их аналогов для фреймов frame.evaluate_handle(), frame.query_selector() или frame.query_selector_all(). После создания ссылки будут удерживать объект от сборки мусора, если только страница не навигируется или ссылка не удаляется вручную с помощью метода 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()
Локатор против ElementHandle
Мы рекомендуем использовать ElementHandle только в редких случаях, когда вам нужно выполнить обширный обход DOM на статической странице. Для всех пользовательских действий и утверждений используйте локатор.
Разница между Locator и ElementHandle заключается в том, что последний указывает на конкретный элемент, в то время как Locator захватывает логику того, как получить этот элемент.
В примере ниже ссылка указывает на конкретный DOM элемент на странице. Если этот элемент изменяет текст или используется React для рендеринга совершенно другого компонента, ссылка все равно указывает на этот устаревший DOM элемент. Это может привести к неожиданным поведением.
- Sync
- Async
handle = page.query_selector("text=Submit")
handle.hover()
handle.click()
handle = await page.query_selector("text=Submit")
await handle.hover()
await handle.click()
С локатором, каждый раз, когда используется локатор, актуальный DOM элемент находится на странице с использованием селектора. Таким образом, в приведенном ниже фрагменте, подлежащий DOM элемент будет найден дважды.
- Sync
- Async
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()