Nightwatch(PageObject)跨页面对象元素访问方法咨询
如何在页面对象文件间共享元素?
当然可以在一个页面对象文件中访问另一个页面对象里定义的元素,而且完全不需要重复定义!下面给你几种实用的实现方式,帮你更高效地维护页面对象代码:
核心结论
不需要重复定义@usernameInput这类跨页面共用的元素,通过合理的代码组织就能实现元素共享,同时保证代码的可维护性。
具体实现方式
方式1:导入目标页面对象直接引用
在需要访问其他页面元素的文件中,直接导入目标页面对象,然后在commands里引用其elements属性即可。
示例代码:
// HomePage.ts import { LoginPage } from './LoginPage'; const page: PageObject = { url: '...', commands: [ { enterUsername: function(query: string) { // 直接使用LoginPage中定义的usernameInput元素 return this.waitForElementVisible(LoginPage.elements.usernameInput); } } ], elements: { // 这里放HomePage专属的元素 } }; export const HomePage = page;
方式2:抽离公共元素到独立文件
如果多个页面共用多个元素,最推荐的方式是把这些公共元素抽离到单独的文件中,让所有需要的页面都导入这个文件。这样既能统一维护元素定位,又避免了重复代码。
示例代码:
// CommonElements.ts export const CommonElements = { usernameInput: { locateStrategy: 'xpath', selector: '//input[@name="Username"]', }, // 可以添加更多跨页面共用的元素 passwordInput: { locateStrategy: 'xpath', selector: '//input[@name="Password"]', } }; // LoginPage.ts import { CommonElements } from './CommonElements'; const page: PageObject = { url: '...', elements: { // 展开公共元素,再添加LoginPage专属元素 ...CommonElements, loginButton: { locateStrategy: 'css', selector: 'button[type="submit"]' } } }; export const LoginPage = page; // HomePage.ts import { CommonElements } from './CommonElements'; const page: PageObject = { url: '...', commands: [ { enterUsername: function(query: string) { return this.waitForElementVisible(CommonElements.usernameInput); } } ], elements: { ...CommonElements, // 这里放HomePage专属的元素 } }; export const HomePage = page;
方式3:调用目标页面对象的已有方法
如果目标页面已经封装了操作该元素的方法,直接调用这个方法会更符合页面对象模式的设计思想——每个页面负责自己的元素操作,其他页面只需调用方法即可,无需关心元素细节。
示例代码:
// LoginPage.ts const page: PageObject = { url: '...', commands: [ { enterUsername: function(query: string) { return this.waitForElementVisible('@usernameInput') .setValue('@usernameInput', query); } } ], elements: { usernameInput: { locateStrategy: 'xpath', selector: '//input[@name="Username"]', } } }; export const LoginPage = page; // HomePage.ts import { LoginPage } from './LoginPage'; const page: PageObject = { url: '...', commands: [ { enterUsernameOnLogin: function(query: string) { // 先跳转到登录页面(如果当前不在登录页),再调用LoginPage的方法 return this.navigateTo(LoginPage.url) .api.perform(() => LoginPage.commands[0].enterUsername.call(this, query)); } } ] }; export const HomePage = page;
总结
- 如果只是偶尔引用其他页面的单个元素,直接导入目标页面对象引用元素是最快的方式;
- 如果存在多个跨页面共用的元素,抽离到公共文件是最优选择,能大幅提升代码的可维护性;
- 优先调用目标页面的已有方法,更符合页面对象模式的职责划分原则。
内容的提问来源于stack exchange,提问作者Jagadeesh
相关产品推荐
相关产品推荐

