uni-app x 页面栈管理指南:getCurrentPages() 与 UniPage 对象的完整解析
【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
在 uni-app x 中,getCurrentPages()是获取当前页面栈实例的核心 API:它以数组形式按栈的顺序返回页面实例,第一个元素为首页,最后一个元素为当前页面。自 HBuilderX 4.31 起,该 API 的返回值升级为UniPage对象数组,开发者可以借此动态读取/修改页面样式(pageStyle)、获取页面原生视图与安全区信息、甚至管理 dialogPage 子弹窗页面栈。本文将结合当前仓库的官方文档与 hello uni-app x 示例工程源码,系统讲解页面栈模型、UniPage 的完整能力、两种 API 风格下的取页面写法,以及基于仓库自动化测试可以验证的实战用法。
getCurrentPages() 与页面栈模型
getCurrentPages()函数用于获取当前页面栈的实例,返回值是一个数组,数组中的元素为页面实例,第一个元素是首页,最后一个元素是当前页面:
const pages = getCurrentPages() // pages[0] -> 首页 // pages[pages.length - 1] -> 当前页面在 uni-app x 中,页面栈是一个先进后出的结构:uni.navigateTo压入新页面、uni.navigateBack弹出页面、uni.switchTab切换 tab 页。通过遍历返回值,可以拿到整个路由链路。
需要特别注意的是:
getCurrentPages()获取的是主页面栈,不能直接获取 dialogPage 页面;- 拿到主页面
UniPage对象后,可以通过getDialogPages()方法获取这个主页面的子弹窗页面栈(dialogPage 栈),详见下文「dialogPage 与主页面栈的关系」; - 选项式 vue 中通过
this.$page是另一种快速获取当前页面对象的方式,它得到的不是一个页面数组,而是一个具体的当前页面,且同时支持主页面与 dialogPage。
兼容性
| Web | 微信小程序 | Android | iOS | iOS(VDOM) UTS 插件 | HarmonyOS | | :- | :- | :- | :- | :- | :- | | 4.0 | 4.41 | 3.9 | 4.11 | 4.31 | 4.61 |
从兼容性表格可以看出:Web、微信小程序、Android、iOS、HarmonyOS 均有完整支持,其中getCurrentPages()返回UniPage对象数组的能力(UniPage 强化)自 HBuilderX 4.31 起在各端逐步就位。
返回值
| 类型 | | :- | | Array<UniPage> |
getCurrentPages()返回的是UniPage对象数组。每个页面是一个UniPage对象,这个对象上有较多方法,比如获取/修改 pageStyle、获取页面高宽与安全区等,完整说明见 UniPage 文档。
UniPage 对象:页面能力的统一入口
在 uni-app x 中,每个页面都对应一个UniPage对象。通过它既可以读取/修改页面的 pageStyle(让 pages.json 中的静态页面配置可以动态修改),也可以继续获取原生页面对象(如 Android 的View、iOS 的UIView),还可以通过vm属性拿到页面的 vue 实例。
UniPage 在 App 与 Web 平台较完善,在小程序端受小程序平台开放度限制,很多能力无法实现,具体以 UniPage 属性兼容性表 为准。
核心属性
| 名称 | 类型 | 兼容性 | 描述 | | :- | :- | :- | :- | | route | string | Web 4.31 / Android 4.31 / iOS 4.31 / HarmonyOS 4.61 | 页面的路由地址 | | options | UTSJSONObject | Web 4.31 / Android 4.31 / iOS 4.31 | 页面的路由参数信息 | | vm | VueComponent | Web 4.31 / Android 4.31 / iOS 4.31 / HarmonyOS 4.61 | UniPage 的 vue 实例对象 | | pageBody | UniPageBody | Web 4.51 / Android 4.51 / iOS 4.51 / HarmonyOS 4.61 | 页面可使用区域信息,单位为 px | | safeAreaInsets | UniSafeAreaInsets | Web 4.51 / Android 4.51 / iOS 4.51 / HarmonyOS 4.61 | 页面安全区域插入位置(与屏幕边界的距离)信息 | | fullscreenElement | UniElement | Android 4.61 / iOS 4.61 / HarmonyOS 4.61 | 已经进入全屏状态的元素 | | width / height | number | Web 4.63 / Android 4.61 / HarmonyOS 4.63 | 页面窗口宽度 / 高度 | | statusBarHeight | number | Web 4.63 / Android 4.61 / HarmonyOS 4.63 | 页面状态栏高度 | |$vm| VueComponent | 已废弃 | 旧版 vue 实例入口,建议改用vm|
其中pageBody(left/right/top/bottom/width/height,均为 number)描述了页面内容可使用区域;safeAreaInsets(left/right/top/bottom)描述页面安全区域与屏幕边界的距离,二者均从 Android/iOS 4.51 起支持。
vm 属性与 $page
vm是页面 vue 实例对象,其属性包括$data、$props、$attrs、$slots、$refs、$parent、$root、$options、$el(类型为 UniElement)以及$page(类型为 UniPage)。也就是说,在页面内this.$page(选项式)或getCurrentInstance()?.proxy?.$page(组合式)拿到的正是当前页面的UniPage实例。
提示:4.31 前仅 Web 与 iOS(非 uts 插件)端支持通过
page.$vm获取 vue 实例;4.31+ 仅 iOS uts 插件环境不支持通过page.vm获取 vue 实例。
直接获取当前页面的 UniPage
HBuilderX 4.32 起,新增了两种直接获取当前页面UniPage实例的快捷方式,无需再手动从数组末尾取值:
// 选项式 API const curPage = this.$page // 组合式 API const currentInstance = getCurrentInstance() const curPage = currentInstance?.proxy?.$page这种写法得到的不是页面数组,而是一个具体的当前页面对象;它既适用于主页面,也适用于 dialogPage。仓库中的 get-current-pages.uvue 示例对$page与getCurrentPages()的等价性做了校验:
const check$page = () : boolean => { const pages = getCurrentPages() const page = pages[pages.length - 1] const $page = currentInstance?.proxy?.$page const res = $page === page console.log('check $page', res) uni.showToast(res ? { title: 'check success' } : { title: 'check fail', icon: 'error' }) return res }如果$page与getCurrentPages()栈顶元素严格相等(===),说明二者指向同一UniPage实例。配套的 component-check-page.uvue 还演示了在组件内通过getCurrentInstance()同样可以拿到所属页面的$page。
dialogPage 与主页面栈的关系
dialogPage 是 HBuilderX 4.31+ 新增的「背景透明页面」,用于制作能覆盖 pages.json 导航栏和 tabBar 的弹框与内置界面(uni.showModal、uni.showActionSheet、uni.showLoading等底层均由此实现)。它与主页面(parentPage)的核心区别在于:
- dialogPage 需要挂在某个主页面上,且不进入主页面栈、不影响路由地址,因此
getCurrentPages()不能直接获取 dialogPage; - 若想获取 dialogPage,需要先拿到其所属主页面(parentPage)的
UniPage,再调用getDialogPages()获取挂载在该主页面上的所有 dialogPage 集合; - dialogPage 在 Android 上不是独立 activity,而是与主页面共用同一个 activity 的全屏 view。
// 获取当前主页面的 UniPage const pages = getCurrentPages() const currentPage = pages[pages.length - 1] // 获取该主页面挂载的所有 dialogPage const dialogPages = currentPage.getDialogPages()getDialogPages()返回Array<UniPage>,兼容性为 Web 4.31 / Android 4.31 / iOS 4.31 / HarmonyOS 4.61,微信小程序不支持(x)。与之配套的getParentPage(): UniPage | null则用于 dialogPage 反向获取所属父页面。dialogPage 的完整机制(uni.openDialogPage/uni.closeDialogPage、生命周期、蒙层处理等)见 dialogPage 文档。
UniPage 的核心方法
除属性外,UniPage提供了一组面向页面管理的实例方法,按用途可分为以下几类。
页面样式:getPageStyle / setPageStyle
getPageStyle(): UTSJSONObject获取当前页面样式,setPageStyle(style: UTSJSONObject): void动态设置页面样式。pages.json 中的page下style节点内容可通过这两个 API 读取与修改,但要注意:
getPageStyle()获取的是UniPage 上最终生效的值,不是 pages.json 里的原始配置;- pages.json 里的内容是静态的,
setPageStyle可以动态设置,但并非所有页面样式都支持动态配置; - 4.31 起,
$getPageStyle/$setPageStyle已废弃(仅为向下兼容保留),不再需要前缀$; - 使用选项式 API 时,不可创建
route、options同名响应式变量,否则会覆盖当前 page 实例的同名属性。
示例(组合式 + uts):
const getPageStyle = () : UTSJSONObject => { const pages: UniPage[] = getCurrentPages() const currentPage = pages[pages.length - 1] return currentPage.getPageStyle() } const setPageStyle = (style : UTSJSONObject) => { const pages = getCurrentPages() const currentPage = pages[pages.length - 1] currentPage.setPageStyle(style) }可动态配置的 PageStyle 属性(来自 unipage.md,注意并非所有 pages.json 的 pageStyle 都可以动态修改):
| 属性 | 类型 | Android | iOS | HarmonyOS | web | 默认值 | | :- | :- | :- | :- | :- | :- | :- | | enablePullDownRefresh | Boolean | 4.13 | 4.13 | 4.61 | 4.13 | false | | backgroundColorContent | String | 4.15 | 4.15 | 4.61 | 4.18 | #ffffff | | navigationBarBackgroundColor | String | 4.18 | 4.18 | 4.61 | 4.18 | #007AFF | | navigationBarTextStyle | String | 4.18 | 4.18 | 4.61 | 4.18 | white | | navigationBarTitleText | String | 4.18 | 4.18 | 4.61 | 4.18 | "" | | navigationStyle | String | x | x | 4.61 | 4.18 | default | | backgroundColor | String | 4.18 | 4.18 | 4.61 | x | #ffffff | | backgroundTextStyle | String | 4.31 | 4.31 | x | x | dark | | onReachBottomDistance | Number | x | x | 4.61 | 4.18 | 50 | | pageOrientation | String | 4.18 | 4.25 | x | x | auto | | disableSwipeBack | Boolean | x | 4.18 | x | x | false | | hideStatusBar | Boolean | 4.31 | x | x | x | false | | hideBottomNavigationIndicator | Boolean | 4.31 | x | x | x | false |
注意事项:
- web 端会自动摇树优化未使用的特性,如果整个项目从未使用过下拉刷新
enablePullDownRefresh,下拉刷新功能会被摇掉,此时动态开启将无效; - app-android 平台的页面是 activity,不支持将
backgroundColorContent设为透明; - 4.15 版本前,app-ios 平台在 pages.json 中将
enablePullDownRefresh设为false时无法通过setPageStyle动态开启,新版已修复。
仓库中的 page-style.uts 定义了可供示例页遍历渲染的PageStyleArray,枚举了可动态配置的键与其可选值,例如navigationBarBackgroundColor(#007AFF / #FFFFFF / #000000)、navigationBarTextStyle(white / black)、navigationStyle(default / custom)、enablePullDownRefresh(true / false)、onReachBottomDistance(50 / 100)、pageOrientation(auto / portrait / landscape)、Android 三键导航相关(androidThreeButtonNavigationTranslucent、androidThreeButtonNavigationBackgroundColor、androidThreeButtonNavigationStyle)等,可直接作为可动态修改属性的权威清单参考。
针对「动态开关下拉刷新」这一典型场景,仓库提供了独立的演示页 set-page-style-disable-pull-down-refresh.uvue:
function setPageStyle(enable : boolean) { // 目前仅支持 enablePullDownRefresh const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; currentPage.setPageStyle({ enablePullDownRefresh: enable }); data.enablePullDownRefreshStatus = enable }原生视图与 Activity:getAndroidView / getAndroidActivity / getIOSView / getHTMLElement
| 方法 | 返回类型 | 兼容性 | 描述 | | :- | :- | :- | :- | | getAndroidView() | View | null | Android 4.31 | 返回 Android 平台页面根 view | | getAndroidActivity() | Activity | null | Android 4.61 | 返回 Android 平台加载页面内容的 Activity | | getIOSView() | UIView | null | iOS(VDOM) UTS 插件 4.33 | 返回 iOS 平台页面根 view | | getHTMLElement() | UniElement | null | Web 4.31 | 返回页面 HTML Element 对象 |
这些方法主要用于 uts 插件场景下与原生层交互,例如在 Android 端拿到页面根 view 或 Activity 后注入原生能力。
DOM 查询:getElementById / querySelector / querySelectorAll
| 方法 | 返回类型 | 兼容性 | 描述 | | :- | :- | :- | :- | | getElementById(id: string.IDString | string) | UniElement | null | Web/Android/iOS 4.31,HarmonyOS 4.61 | 返回匹配特定 ID 的元素,不存在返回 null;ID 区分大小写且应唯一 | | querySelector(selector: string.cssSelectorString) | UniElement | null | Web/Android/iOS/HarmonyOS 5.0 | 返回页面中与选择器匹配的第一个元素,找不到返回 null | | querySelectorAll(selector: string.cssSelectorString) | UniElement[] | Android/iOS/HarmonyOS 5.0,iOS(VDOM) UTS 插件 5.21 | 返回页面中与选择器匹配的元素列表 |
getElementById如果需要获取指定的节点类型,需要使用as进行类型转换。这一组方法让页面级 DOM 查询成为可能,与全局的uni.getElementById(仅获取栈顶元素)相比,它们可以在指定页面的UniPage对象上操作,因而也适用于 dialogPage 内部元素。
截图与全屏:takeSnapshot / exitFullscreen
takeSnapshot(options: TakeSnapshotOptions): void对当前页面内容进行截图(5.02 起支持 Android/iOS/HarmonyOS)。注意:只针对页面内容截图,不包含状态栏、软键盘等系统 UI 元素,也不包含 pages.json 中定义的导航栏与 tabBar。截图行为随页面内容大小、根节点类型与平台不同而有所差异:
| 页面内容 | 根节点类型 | 截图高度 | | :- | :- | :- | | 超过一屏 | scroll-view 滚动容器 | 长图(完整内容) | | 超过一屏 | 非 scroll-view 容器 | 长图(完整内容),iOS 例外为屏幕高度 | | 不超过一屏 | scroll-view 滚动容器 | 内容高度(内容多高截图就多高) | | 不超过一屏 | 非 scroll-view 容器 | 屏幕高度(固定一屏高) |
options 参数:type(默认"file",目前仅支持保存到临时文件目录)、format(默认"png")、success(返回tempFilePath临时文件路径)、fail、complete回调。
exitFullscreen(options: ExitFullscreenOptions): void(Android/iOS/HarmonyOS 4.61)用于逆转此前 UniElement.requestFullscreen 的全屏效果,其fail回调中的errCode取值包括:106600(当前页面已有 element 处于全屏状态)、106601(当前 element 不支持全屏)、106602(当前页面没有 element 处于全屏状态)、106603(页面已销毁或尚未就绪)、106604(组件未就绪)。
监听类方法(HarmonyOS Vapor 5.0+)
UniPage 还提供一组以on/off配对的事件监听方法,返回 number 类型的监听 id,可用于取消监听:
onLayoutChange/offLayoutChange:监听/取消页面布局变化,回调参数UniPagePerformanceTiming(duration,单位 ms);onRenderChange/offRenderChange:监听/取消页面渲染变化,回调参数UniPagePerformanceRenderTiming(updateDuration、duration,单位 ms);onTouchStart/offTouchStart、onTouchEnd/offTouchEnd:监听/取消页面触摸开始、结束事件,回调参数为 UniTouchEvent。
此外还有createElement(tagName: string): UniElement(HarmonyOS(VDOM) 4.63,创建组件),它们共同构成页面的低层能力集合。
仓库示例与自动化测试验证
getCurrentPages的完整可运行示例位于 src/pages/API/get-current-pages/get-current-pages.uvue,该页面在 pages.json 中注册,并通过group: "1,0,1"携带测试参数;set-page-style-disable-pull-down-refresh演示页则在 pages.json 中注册,enablePullDownRefresh默认配置为false。
示例页的核心逻辑(节选):
const _getCurrentPages = () => { data.pages.length = 0 const pages = getCurrentPages() data.pages.push(pages[0].route) // 首页 route for (let i = 1; i < pages.length; i++) { data.pages.push(pages[i].route) // 逐层输出页面栈 } }自动化测试 get-current-pages.test.js 以 jest + 自动化驱动的方式,在 Android / iOS / HarmonyOS / Web / 小程序多端对本文介绍的能力逐项断言,可作为「哪些能力真实可用」的直接证据:
getCurrentPages:跳转到pages/API/get-current-pages/get-current-pages?test=123后调用_getCurrentPages,断言首页 route 命中 tabBar 首页,验证页面栈顺序;$page:通过page.callMethod('check$page')断言$page === getCurrentPages()栈顶,并验证组件内$page同样等价;page-style:调用setPageStyle({ enablePullDownRefresh: false })后getPageStyle()断言生效值翻转,并配合startPullDownRefresh截图比对;随后验证 Android 三键导航(androidThreeButtonNavigationBackgroundColor/androidThreeButtonNavigationStyle/androidThreeButtonNavigationTranslucent)与hideStatusBar、hideBottomNavigationIndicator的动态设置;getParentPage/getDialogPages:在主页面栈场景断言getParentPage()为 null、getDialogPages()为空数组(弹窗场景下的取值见 dialog-page 文档);getElementById/querySelector/querySelectorAll:断言#check-get-element-by-id-btn可查、#does-not-exist不可查,querySelectorAll('.uni-common-mt')数量大于 1 且不存在的类返回空列表;getAndroidView:仅 Android 端返回非空;getHTMLElement:仅 Web 端返回非空;getAndroidActivity:仅 Android 端断言成功;takeSnapshot:App 端调用后断言 success/complete 回调计数,验证截图链路。
这套测试同时印证了各方法的平台适用性边界:例如getAndroidView仅在 Android 断言通过,getIOSView在非 iOS(VDOM) UTS 插件环境断言为 false,getHTMLElement仅在 Web 为 true——与上文的兼容性表格完全对应。
实战要点与最佳实践
- 取当前页面:组合式 API 优先使用
getCurrentInstance()?.proxy?.$page,选项式使用this.$page;若在页面脚本中需要遍历整条链路,再使用getCurrentPages()并从末尾取当前页。 - 读取路由参数:
UniPage.options(UTSJSONObject)携带页面路由参数,例如get-current-pages.test.js中通过?test=123传入的参数可在page.options['test']读取。 - 动态样式:
setPageStyle只对表格中列出的属性生效,且各平台版本门槛不同;设置前可先getPageStyle()读取当前最终生效值再按需合并修改,避免覆盖其他属性。 - dialogPage 场景:
getCurrentPages()拿不到 dialogPage,必须先从主页面UniPage的getDialogPages()获取;在 dialogPage 内部取自身页面实例,应使用this.$page/$page。 - 原生能力:uts 插件开发中,通过
getAndroidView()/getAndroidActivity()/getIOSView()获取原生根视图与容器,是连接 uni-app x 页面与原生 SDK 的常用入口;注意getIOSView仅限 iOS(VDOM) UTS 插件环境。 - Web 摇树提醒:在 web 端使用
setPageStyle({ enablePullDownRefresh: true })前,需确保项目某处真正使用过下拉刷新能力,否则相关代码会被摇树优化移除,导致动态开启无效。
参见
- UniPage 完整属性与方法文档
- dialogPage 概述与 openDialogPage / closeDialogPage
- UTSJSONObject 内置对象文档
- UniElement DOM 元素文档
- 示例页源码
- 自动化测试用例
【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考