
简体中文
HBuilderX 4.31+新增了dialogPage,适用于制作弹框和内置界面。
dialogPage是一种背景透明的页面,可以覆盖pages.json中的导航栏和tabbar。之前的page被称为主page或parentPage。dialogPage需要挂在主page上。
dialogPage是一种特殊的page,它和主page有很多相同之处:
dialogPage和主page的区别:
openDialogPage
和closeDialogPage
uni.getElementById
是无法获取到dialogPage内的元素的。因为uni这个全局API是获取栈顶元素。如果想获取指定页面的元素,需获取到指定页面的UniPage对象,在这个对象上使用.getElementById方法。如果想获取当前dialogPage页面的元素,应该使用this.$page.getElementById()
。dialogPage的绑定:
openDialogPage
时可通过 parentPage
参数指定所属页面,不指定时默认为当前页面。多dialogPage注意事项:
调用时机注意事项:
app-android平台注意事项:
打开模态弹窗页面
Web | 微信小程序 | Android | iOS | iOS uni-app x UTS 插件 | HarmonyOS |
---|---|---|---|---|---|
4.31 | x | 4.31 | 4.31 | 4.31 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | OpenDialogPageOptions | 是 | - | 打开 dialogPage 参数 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errCode | number | 是 | - | 路由错误码 - 4: 框架内部异常 | |
errSubject | string | 是 | - | 统一错误主题(模块)名称 | |
data | any | 否 | - | 错误信息中包含的数据 | |
cause | Error | 否 | - | 源错误信息,可以包含多个错误,详见SourceError | |
errMsg | string | 是 | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - |
类型 | 必备 |
---|---|
UniPage | 否 |
关闭模态弹窗页面
closeDialogPage
可通过 dialogPage
参数指定要关闭的 dialogPage
, 不指定时默认关闭当前页面的所有 dialogPage
。
Web | 微信小程序 | Android | iOS | iOS uni-app x UTS 插件 | HarmonyOS |
---|---|---|---|---|---|
4.31 | x | 4.31 | 4.31 | 4.31 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | CloseDialogPageOptions | 否 | - | 关闭 dialogPage 参数 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errCode | number | 是 | - | 路由错误码 - 4: 框架内部异常 | |
errSubject | string | 是 | - | 统一错误主题(模块)名称 | |
data | any | 否 | - | 错误信息中包含的数据 | |
cause | Error | 否 | - | 源错误信息,可以包含多个错误,详见SourceError | |
errMsg | string | 是 | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - |
类型 |
---|
null |
示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见
示例
<template>
<!-- #ifdef APP -->
<scroll-view style="flex: 1;">
<!-- #endif -->
<view class="uni-padding-wrap">
<view class="uni-common-mt flex-row" v-if="pageBody != null">pageBody: {
top: <text id="page-body-top">{{pageBody!.top}}</text>,
right: <text id="page-body-right">{{pageBody!.right}}</text>,
bottom: <text id="page-body-bottom">{{pageBody!.bottom}}</text>,
left: <text id="page-body-left">{{pageBody!.left}}</text>,
width: <text id="page-body-width">{{pageBody!.width}}</text>,
height: <text id="page-body-height">{{pageBody!.height}}</text>
}
</view>
<view class="uni-common-mt flex-row" v-if="safeAreaInsets != null">safeAreaInsets: {
top: <text id="page-safe-area-insets-top">{{safeAreaInsets!.top}}</text>,
right: <text id="page-safe-area-insets-right">{{safeAreaInsets!.right}}</text>,
bottom: <text id="page-safe-area-insets-bottom">{{safeAreaInsets!.bottom}}</text>,
left: <text id="page-safe-area-insets-left">{{safeAreaInsets!.left}}</text>}
</view>
<!-- #ifdef APP-ANDROID || APP-IOS || APP-HARMONY || WEB -->
<view class="uni-common-mt flex-row" v-if="width != null">width: <text id="page-width">{{width!}}</text>
</view>
<view class="uni-common-mt flex-row" v-if="height != null">height: <text id="page-height">{{height!}}</text>
</view>
<view class="uni-common-mt flex-row" v-if="statusBarHeight != null">statusBarHeight: <text id="page-statusBarHeight">{{statusBarHeight!}}</text>
</view>
<!-- #endif -->
<button class="uni-common-mt" id="go-next-page" @click="goNextPage">
go next page
</button>
<button class="uni-common-mt" id="open-dialog1" @click="openDialog1">
open dialog 1
</button>
<button class="uni-common-mt" id="open-dialog1-wrong-path" @click="openDialog1WrongPath">
open dialog page 1 with wrong path
</button>
<button class="uni-common-mt" id="go-next-page-open-dialog1" @click="goNextPageOpenDialog1">
go next page & open dialog1
</button>
<button class="uni-common-mt" id="open-dialog1" @click="openDialog3">
open dialog 3 test page style
</button>
<button class="uni-common-mt" id="open-dialog4" @click="openDialogWithTriggerParentHide">
openDialog with triggerParentHide
</button>
<button class="uni-common-mt" id="open-dialog5" @click="openDialogCheckMoreAttribute">
openDialog check more attribute
</button>
<button class="uni-common-mt" id="open-dialog5" @click="openDialogWithRelativePath">
openDialog with relative path
</button>
<text class="uni-common-mt choose-open-animation-type-title">choose open dialogPage animationType</text>
<radio-group class="choose-open-animation-type-radio-group" @change="handleOpenAnimationType">
<radio class="ml-10 uni-common-mt" v-for="item in openAnimationTypeList" :key="item" :value="item"
:checked="openAnimationType == item">{{ item }}
</radio>
</radio-group>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script lang="uts">
import {
state,
setLifeCycleNum
} from '@/store/index.uts'
type OpenAnimationType =
'auto' |
'none' |
'slide-in-right' |
'slide-in-left' |
'slide-in-top' |
'slide-in-bottom' |
'fade-in' |
'zoom-out' |
'zoom-fade-out'
export default {
data() {
return {
pageBody : null as UniPageBody | null,
safeAreaInsets: null as UniSafeAreaInsets | null,
width: null as number | null,
height: null as number | null,
statusBarHeight: null as number | null,
jest_click_x: -1,
jest_click_y: -1,
openAnimationType: 'none' as OpenAnimationType,
openAnimationTypeList: [
'auto',
'none',
'slide-in-right',
'slide-in-left',
'slide-in-top',
'slide-in-bottom',
'fade-in',
'zoom-out',
'zoom-fade-out'
]
}
},
onLoad() {
console.log('dialogPage parent onLoad')
},
onShow() {
console.log('dialogPage parent onShow')
setLifeCycleNum(state.lifeCycleNum + 10)
},
onReady() {
console.log('dialogPage parent onReady')
const currentPage = this.$page
this.pageBody = currentPage.pageBody;
this.safeAreaInsets = currentPage.safeAreaInsets
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY || WEB
this.width = currentPage.width
this.height = currentPage.height
this.statusBarHeight = currentPage.statusBarHeight
// #endif
},
onHide() {
console.log('dialogPage parent onHide')
setLifeCycleNum(state.lifeCycleNum - 10)
},
onUnload() {
console.log('dialogPage parent onUnload')
},
methods: {
goNextPage() {
uni.navigateTo({
url: '/pages/API/dialog-page/next-page'
})
},
openDialog1() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-1?name=dialog1',
animationType: this.openAnimationType,
success(res) {
console.log('openDialogPage1 success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialogPage1 fail', err)
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialogPage1 complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
openDialog2() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-2',
animationType: this.openAnimationType,
disableEscBack: true,
success(res) {
console.log('openDialog2 success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialog2 fail', err)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialog2 complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
openDialog1WrongPath() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-11?name=dialog1',
success(res) {
console.log('openDialogPage1 success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialogPage1 fail', err)
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialogPage1 complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
goNextPageOpenDialog1() {
uni.navigateTo({
url: '/pages/API/dialog-page/next-page',
success() {
setTimeout(() => {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-1?name=dialog1',
animationType: this.openAnimationType,
success(res) {
console.log('openDialogPage1 success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialogPage1 fail', err)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialogPage1 complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
}, 2000)
}
})
},
closeDialog() {
uni.closeDialogPage({
success(res) {
console.log('closeDialog success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('closeDialog fail', err)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('closeDialog complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
closeSpecifiedDialog(index : number) {
const dialogPages = this.$page.getDialogPages()
uni.closeDialogPage({
dialogPage: dialogPages[index],
success(res) {
console.log('closeSomeOneDialog success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('closeSomeOneDialog fail', err)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('closeSomeOneDialog complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
// 自动化测试
openDialog4() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-4',
})
},
openDialogWithTriggerParentHide() {
uni.openDialogPage({
url: `/pages/API/dialog-page/dialog-4?tag=${Date.now()}`,
triggerParentHide: true,
success(res) {
console.log('openDialogWithTriggerParentHide success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialogWithTriggerParentHide fail', err)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialogWithTriggerParentHide complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
openDialogCheckMoreAttribute(){
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-5',
})
},
setLifeCycleNum(value : number) {
setLifeCycleNum(value)
},
getLifeCycleNum() : number {
return state.lifeCycleNum
},
jest_OpenDialog1() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-1?name=dialog1'
})
},
jest_CloseDialog1() {
uni.closeDialogPage({})
},
jest_getTapPoint() {
const systemInfo = uni.getSystemInfoSync()
let ratio = 1
if (systemInfo.platform == 'android') {
ratio = systemInfo.devicePixelRatio
}
this.jest_click_x = systemInfo.screenWidth / 2 * ratio
this.jest_click_y = systemInfo.statusBarHeight * ratio + 10
},
openDialog2ForTest() {
uni.openDialogPage({
url: '/pages/API/dialog-page/dialog-2'
});
},
closeDialog2ForTest() {
uni.closeDialogPage({});
},
setPageStyleForTest(style : UTSJSONObject) {
const pages = this.$page.getDialogPages();
if (pages.length > 0) pages[pages.length - 1].setPageStyle(style);
},
setPageStyleForTest2(style : UTSJSONObject) {
this.$page.setPageStyle(style);
},
openDialog3() {
uni.openDialogPage({ url: '/pages/API/dialog-page/dialog-3', animationType: this.openAnimationType })
},
handleOpenAnimationType(e : RadioGroupChangeEvent) {
this.openAnimationType = e.detail.value as OpenAnimationType
},
openDialogWithRelativePath(){
uni.openDialogPage({
url: './dialog-1?name=dialog1',
animationType: this.openAnimationType,
success(res) {
console.log('openDialogPage1 success', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(err) {
console.log('openDialogPage1 fail', err)
setLifeCycleNum(state.lifeCycleNum - 4)
},
complete(res) {
console.log('openDialogPage1 complete', res)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
}
})
},
// 自动化测试
getDialogPage() : UniPage | null {
const dialogPages = this.$page.getDialogPages()
return dialogPages.length > 0 ? dialogPages[0] : null
},
// 自动化测试
getDialogPageRoute() : string {
const dialogPage = this.getDialogPage()
if(dialogPage != null){
return dialogPage.route
}
return ''
},
// 自动化测试
dialogPageCheckGetDialogPages() : boolean {
const dialogPage = this.getDialogPage()!
const dialogPages = dialogPage.getDialogPages()
const res = dialogPages.length == 0
return res
},
// 自动化测试
dialogPageGetPageStyle() : UTSJSONObject {
const dialogPage = this.getDialogPage()!
return dialogPage.getPageStyle()
},
// 自动化测试
dialogPageSetPageStyle() {
const dialogPage = this.getDialogPage()!
dialogPage.setPageStyle({
backgroundColorContent: 'red'
})
},
// 自动化测试
dialogPageCheckGetElementById() : boolean {
const dialogPage = this.getDialogPage()!
const element = dialogPage.getElementById('dialog1-go-next-page')
let res = element != null
// #ifndef APP-ANDROID
if (res) {
const elPage = element!.getPage()
console.log('elPage', elPage)
res = elPage === dialogPage
}
// #endif
return res
},
// 自动化测试
dialogCheckGetAndroidView() : boolean {
const dialogPage = this.getDialogPage()!
const androidView = dialogPage.getAndroidView()
const res = androidView != null
return res
},
// 自动化测试
dialogCheckGetIOSView() : boolean {
const dialogPage = this.getDialogPage()!
const IOSView = dialogPage.getIOSView()
const res = IOSView != null
return res
},
// 自动化测试
dialogCheckGetHTMLElement() : boolean {
const dialogPage = this.getDialogPage()!
const HTMLView = dialogPage.getHTMLElement()
const res = HTMLView != null
return res
},
}
}
</script>
<style>
.uni-padding-wrap{
padding-bottom: var(--uni-safe-area-inset-bottom);
}
.ml-10 {
margin-left: 10px;
}
.choose-open-animation-type-title {
font-weight: bold;
}
.choose-open-animation-type-radio-group {
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 20px;
}
.flex-row{
flex-direction: row;
flex-wrap: wrap;
}
</style>style>
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - | 错误信息 |
dialogPage
。// 1. 通过 parentPage 获取 dialogPage 集合
const pages = getCurrentPages()
// 获取当前页面
const page = pages[pages.length-1]
// 获取当前页面的 `dialogPage` 集合
const dialogPages = page.getDialogPages()
// 2. 在 dialogPage 中通过 this.$page 获取 dialogPage 实例 (组件中不支持)
// 选项式 API
const dialogPage = this.$page
// 组合式 API
const currentInstance = getCurrentInstance()
const dialogPage = instance?.proxy?.$page
dialogPage
,在 App 端不会随 tabBar 页面切换而隐藏,在 Web 端会随 tabBar 页面切换而隐藏。