定位 Frames 内嵌框架
本教程共 59 篇 · 第 15 篇 · 更新于 2026-08-04 · 约 8 分钟阅读
本节目标:搞懂页面里的 iframe(内嵌框架)怎么进、怎么在里面定位元素,掌握 frameLocator 和 page.frame 两种入口,并知道跨框架操作的限制。
什么是 Frame
一个 Page(页面)底下可以挂一个或多个 Frame(框架)。每个页面都有一个主框架(main frame),页面级操作默认都发生在这里。
用 <iframe> 标签还能往里嵌额外的框架。框架内部是独立的一份文档,外面的定位器进不去,里面的也出不来。想操作框架里的元素,得先「切」进去。
首选:frameLocator
最推荐的入口是 page.frameLocator()。它返回一个 FrameLocator(框架定位器),拿到之后就能像在 page 上一样,继续用熟悉的 getByLabel、getByRole。
// 进到 class 为 frame-class 的框架里,按标签找用户名框
const username = page.frameLocator('.frame-class').getByLabel('User Name');
await username.fill('John');
链式很自然:框架定位器上调方法,返回的定位器就落在框架内部。
await page
.frameLocator('#my-frame')
.getByRole('button', { name: 'Sign in' })
.click();
Note第 9 章说过:创建定位器的方法在
page、Locator、FrameLocator上都有。所以frameLocator(...).getByRole(...)这种链式是顺理成章的。
如果那个 iframe 本身不好用 CSS 描述,可以先把它当普通元素定位到,再用 contentFrame() 跳进去:
// 先定位 iframe 元素,再切进它的内容
const frame = page.getByTitle('支付表单').contentFrame();
await frame.getByLabel('卡号').fill('4242424242424242');
反过来也行:frameLocator.owner() 能拿回承载它的那个 <iframe> 元素。想断言 iframe 自身可见时用得上。
另一种:page.frame 拿 Frame 对象
想要更「命令式」的访问,用 page.frame() 直接拿 Frame 对象。它支持按 name 属性或 URL 查找。
// 按框架的 name 属性找
const loginFrame = page.frame('frame-login');
await loginFrame?.fill('#username-input', 'John');
// 按框架的 URL 找(支持正则)
const domainFrame = page.frame({ url: /.*domain.*/ });
await domainFrame?.click('#submit');
注意 page.frame() 可能返回 null——框架还没加载出来就找不到。TypeScript 会逼你处理这个分支,上面用了 ?.。
Tip两者的区别新手容易含糊。
frameLocator返回的是「定位器」,自带自动等待和重试;page.frame返回的是「对象」,取到那一刻框架必须已经存在。日常测试一律优先frameLocator。
跨框架的限制
框架之间是隔离的。几条基本规则要心里有数:
- 主框架的定位器,找不到 iframe 内部的元素。
- 框架内部的定位器,也出不了自己的框架。
- 要操作哪一层,就用对应的
frameLocator切进去。
当页面套了多层 iframe,就一层层 frameLocator 往下切:
await page
.frameLocator('#outer')
.frameLocator('#inner')
.getByText('内容')
.click();
小结
操作 iframe,首选 page.frameLocator() 切进去,再接用户视角的定位器,这条路最稳。iframe 本身难描述时,用 locator.contentFrame() 从元素跳进内容。需要命令式访问才动用 page.frame()。
框架彼此隔离,要操作哪一层就切到哪一层,套了几层就切几次。
下一章预告:Shadow DOM 与复杂 DOM 定位技巧——Playwright 默认能穿透开放的 Shadow Root,以及定位不稳定时怎么排查。