本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、模态页面核心概念
1. 功能定位
- 作用:中断用户当前操作流,强制用户完成特定任务后才能返回(如登录、授权、支付)。
- 与非模态区别:
特性 模态页面 非模态页面 交互方式 必须主动关闭 可随时切换 堆栈管理 独立于页面栈 遵循常规页面导航栈 典型场景 支付弹窗、权限申请 设置页、详情页
2. 两种实现方式
类型 | API | 特点 |
---|---|---|
全屏模态 | router.pushUrl + mode: 'modal' | 覆盖整个屏幕,带透明蒙层 |
弹窗模态 | @ohos.promptAction.showDialog | 居中弹窗,尺寸可定制 |
二、基础使用与API详解
1. 全屏模态页面
定义模态页面
// ModalPage.ets
@Entry
@Component
struct ModalPage {
@State inputText: string = '';
build() {
Column() {
TextInput({ placeholder: '请输入验证码' })
.onChange((value: string) => this.inputText = value)
Button('确认')
.onClick(() => {
router.back({ result: { code: this.inputText } }); // 返回并携带结果
})
}
.width('100%')
.height('100%')
.backgroundColor(Color.White)
}
}
调用模态页面
// MainPage.ets
import router from '@ohos.router';
@Entry
@Component
struct MainPage {
async openModal() {
try {
const result = await router.pushUrl({
url: 'pages/ModalPage',
params: { title: '身份验证' }, // 传递参数
mode: 'modal' // 关键:设置为模态
});
console.log('返回结果:', result?.code); // 接收模态页返回数据
} catch (err) {
console.error('打开失败:', err);
}
}
build() {
Column() {
Button('打开模态页')
.onClick(() => this.openModal())
}
}
}
关键API:
router.pushUrl
的mode: 'modal'
参数。router.back()
的result
参数传递返回数据。
2. 弹窗模态(Dialog)
import promptAction from '@ohos.promptAction';
function showCustomDialog() {
promptAction.showDialog({
title: '删除确认',
message: '确定删除该文件?此操作不可撤销',
buttons: [
{ text: '取消', color: '#999' },
{ text: '删除', color: '#FF0000' }
]
}).then((result: { index: number }) => {
if (result.index === 1) {
// 用户点击了"删除"
this.deleteFile();
}
});
}
配置参数:
title/message
:标题和内容。buttons
:自定义按钮文本和样式。alignment
:弹窗位置(API 12+支持DialogAlignment.Top
等)。
三、高级功能实战
1. 动态控制模态样式
// 自定义蒙层和动画
router.pushUrl({
url: 'pages/ModalPage',
mode: 'modal',
modalTransition: {
enter: {
effect: ScaleEffect({ scale: 0.8 }), // 缩放进入
duration: 300
},
exit: {
effect: TranslateEffect({ y: 1000 }), // 下滑退出
duration: 200
}
},
modalStyle: {
backgroundColor: '#66000000', // 半透明黑色蒙层
dimEnabled: true // 点击蒙层是否关闭(默认true)
}
});
2. 模态页面间数据通信
父页面向模态页传参
// MainPage.ets
router.pushUrl({
url: 'pages/ModalPage',
params: {
userId: '123',
onConfirm: (data: string) => { // 回调函数
this.handleConfirm(data);
}
},
mode: 'modal'
});
// ModalPage.ets
@State userId: string = '';
private onConfirm?: (data: string) => void;
aboutToAppear() {
this.userId = router.getParams()?.['userId'];
this.onConfirm = router.getParams()?.['onConfirm'];
}
Button('提交')
.onClick(() => {
this.onConfirm?.(this.inputText);
router.back();
})
3. 嵌套模态页面管理
// 在第一个模态页中打开第二个模态页
router.pushUrl({
url: 'pages/SecondModalPage',
mode: 'modal'
});
// 关闭所有模态页
router.clear('modal'); // API 12+
四、完整案例:支付流程模态
// PaymentModal.ets
@Entry
@Component
struct PaymentModal {
@State amount: number = 100;
@State cardNumber: string = '**** **** **** 1234';
build() {
Column() {
Text(`支付金额:¥${this.amount}`).fontSize(20)
Text(`卡号:${this.cardNumber}`).margin({ top: 20 })
Radio({ group: 'method' })
.options([
{ value: 'wechat', name: '微信支付' },
{ value: 'alipay', name: '支付宝' }
])
Button('确认支付', { type: ButtonType.Capsule })
.margin({ top: 30 })
.onClick(() => {
router.back({
result: {
success: true,
orderId: Date.now().toString()
}
});
})
}
.padding(20)
.width('100%')
.height('100%')
.backgroundColor(Color.White)
}
}
// 调用支付模态页
async function pay() {
const result = await router.pushUrl({
url: 'pages/PaymentModal',
mode: 'modal',
modalStyle: {
dimEnabled: false // 禁用蒙层点击关闭
}
});
if (result?.success) {
showToast('支付成功');
}
}
功能扩展:
- 增加密码输入组件。
- 集成支付SDK验证逻辑。
五、调试与性能优化
1. 生命周期监控
// ModalPage.ets
aboutToAppear() {
console.log('模态页创建');
}
aboutToDisappear() {
console.log('模态页销毁');
}
2. 内存优化建议
场景 | 优化措施 |
---|---|
频繁打开模态页 | 使用router.clear() 清理历史栈 |
大图资源模态页 | 预加载图片并监听aboutToDisappear 释放 |
六、总结对比
实现方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
全屏模态 | 完全控制UI,支持复杂交互 | 需单独创建页面文件 | 支付流程、表单填写 |
Dialog弹窗 | 快速实现,无需新页面 | 样式定制受限 | 简单确认对话框 |