ionic 模态窗口

Ionic 模态窗口(Modal)完整实战指南

(Ionic 7+,支持 Angular / React / Vue 都通用)

ion-modal 是 Ionic 最强大的弹窗组件,比 alert 更灵活、比 popover 更大、支持任意页面内容!

1. 基本使用(90% 场景都这么写)

// 在任意页面或服务中注入
import { ModalController } from '@ionic/angular';

constructor(private modalCtrl: ModalController) {}

// 打开模态窗口
async openModal() {
  const modal = await this.modalCtrl.create({
    component: DetailPage,        // 要弹出的页面组件
    componentProps: {            // 传参给弹窗页面
      id: 123,
      name: '张三'
    },
    cssClass: 'my-modal',        // 自定义样式
    backdropDismiss: true,       // 点击背景关闭
    showBackdrop: true,          // 显示背景遮罩
    mode: 'ios',                 // 强制 iOS 风格
    // animated: false           // 关闭动画(调试用)
  });

  await modal.present();

  // 接收弹窗返回的数据
  const { data, role } = await modal.onWillDismiss();
  if (role === 'confirm') {
    console.log('用户点击了确定,返回数据:', data);
  }
}

2. 被弹出的页面(DetailPage)怎么接收参数和返回数据?

// detail.page.ts
import { Component, Input } from '@angular/core';
import { ModalController } from '@ionic/angular';

@Component({
  selector: 'app-detail',
  templateUrl: 'detail.page.html'
})
export class DetailPage {
  @Input() id: number;
  @Input() name: string;

  constructor(private modalCtrl: ModalController) {}

  // 关闭并返回数据
  confirm() {
    this.modalCtrl.dismiss({
      selectedItem: '苹果',
      count: 5
    }, 'confirm');
  }

  // 取消关闭
  cancel() {
    this.modalCtrl.dismiss(null, 'cancel');
  }
}
<!-- detail.page.html -->
<ion-header>
  <ion-toolbar>
    <ion-title>商品详情</ion-title>
    <ion-buttons slot="end">
      <ion-button (click)="cancel()">关闭</ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <h2>ID: {{ id }}</h2>
  <p>你好,{{ name }}!</p>
  <ion-button expand="block" (click)="confirm()">确认购买</ion-button>
</ion-content>

3. 超实用样式大全(直接复制就美)

样式需求代码写法效果说明
小窗口(50% 宽)cssClass: 'small-modal'登录、表单
全屏模态cssClass: 'full-modal'图片预览、地图
底部抽屉式cssClass: 'bottom-modal', breakpoints: [0, 0.4, 0.8, 1], initialBreakpoint: 0.4评论、分享
从底部滑出enterAnimation, leaveAnimation微信式弹窗
透明背景--background: transparent自定义动画

推荐:底部抽屉式模态(超火!)

const modal = await this.modalCtrl.create({
  component: CommentPage,
  breakpoints: [0, 0.3, 0.5, 0.8, 1],  // 可停留的高度
  initialBreakpoint: 0.5,               // 初始高度 50%
  handle: true,                         // 显示顶部拖拽条
  backdropDismiss: true
});

4. 自定义动画(从底部滑入)

import { AnimationController } from '@ionic/angular';

async openBottomModal() {
  const modal = await this.modalCtrl.create({
    component: SharePage,
    enterAnimation: this.enterAnimation,
    leaveAnimation: this.leaveAnimation
  });
  await modal.present();
}

// 自定义进入动画
enterAnimation = (baseEl: HTMLElement) => {
  const backdrop = baseEl.querySelector('ion-backdrop')!;
  const wrapper = baseEl.querySelector('.modal-wrapper')!;

  const backdropAnimation = this.animationCtrl
    .create()
    .addElement(backdrop)
    .fromTo('opacity', 0, 0.6);

  const wrapperAnimation = this.animationCtrl
    .create()
    .addElement(wrapper)
    .fromTo('transform', 'translateY(100%)', 'translateY(0)')
    .fromTo('border-radius', '20px 20px 0 0', '0');

  return this.animationCtrl
    .create()
    .addElement(baseEl)
    .duration(400)
    .easing('cubic-bezier(0.36,0.66,0.04,1)')
    .addAnimation([backdropAnimation, wrapperAnimation]);
};

5. 全局封装(推荐放 service)

// modal.service.ts
@Injectable({ providedIn: 'root' })
export class ModalService {
  constructor(private modalCtrl: ModalController) {}

  async open(component: any, props?: any, cssClass = '') {
    const modal = await this.modalCtrl.create({
      component,
      componentProps: props,
      cssClass,
      backdropDismiss: true
    });
    await modal.present();
    return modal;
  }

  async openBottom(component: any, props?: any) {
    return this.open(component, props, 'bottom-modal');
  }
}

6. 常见问题速查

问题解决方案
键盘遮挡输入框ion-contentscroll-y="true"
模态窗口内容不滚动在弹窗页面加 <ion-content>
想让模态窗口不可关闭backdropDismiss: false + 提供关闭按钮
多个模态叠加支持!后打开的在上层
关闭所有模态this.modalCtrl.dismiss(null, null, null, true)

7. 一句话总结最优雅写法

const modal = await this.modalCtrl.create({
  component: MyPage,
  componentProps: { id: 1 },
  breakpoints: [0, 0.5, 1],
  initialBreakpoint: 0.5,
  handle: true
});
await modal.present();
const { data } = await modal.onDidDismiss();

这样写出来的模态窗口,iOS 是毛玻璃抽屉,Android 是丝滑上滑,体验完美!

需要我直接发你一个「图片预览 + 手势缩放 + 底部评论抽屉」的完整可运行模板吗?一句话就发~

文章已创建 2588

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部