Skip to content

Modal 模态框

介绍

模态框组件,用于向用户展示提示信息、确认操作等场景,支持标题、内容、取消/确认按钮、关闭前拦截、自定义内容等功能。

引入

typescript
import { TnModal } from "@tuniao/tn-ui";

代码演示

基础用法

通过 visible 控制模态框的显示与隐藏,title 设置标题,content 设置内容文本。默认只显示确认按钮。

基础用法

点我查看代码
typescript
import { TnModal } from "@tuniao/tn-ui";

@Entry
@ComponentV2
struct ModalBasic {
  @Local visible: boolean = false;

  build() {
    Column() {
      Button("基础模态框")
        .onClick(() => {
          this.visible = true;
        })
      TnModal({
        visible: this.visible,
        $visible: (visible: boolean) => {
          this.visible = visible;
        },
        title: "提示",
        content: "这是一个基础模态框示例",
      })
    }
  }
}

无标题模态框

不设置 title 属性时,模态框将不显示标题区域,内容区域会自动调整内边距。

无标题模态框

点我查看代码
typescript
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  content: "这是一个没有标题的模态框",
})

带取消按钮

通过 showCancel 属性显示取消按钮,同时可以监听 onConfirmonCancel 事件。

带取消按钮

点我查看代码
typescript
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "确认操作",
  content: "是否确认删除此项目?删除后不可恢复。",
  showCancel: true,
  onConfirm: () => {
    console.info("点击了确认");
  },
  onCancel: () => {
    console.info("点击了取消");
  },
})

自定义按钮文字

通过 cancelTextconfirmText 属性自定义取消和确认按钮的文字。

自定义按钮文字

点我查看代码
typescript
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "退出登录",
  content: "确定要退出当前账号吗?",
  showCancel: true,
  cancelText: "再想想",
  confirmText: "立即退出",
})

自定义按钮颜色

通过 confirmButtonColorcancelButtonColor 属性自定义按钮文字颜色。

自定义按钮颜色

点我查看代码
typescript
import { TnModal, getThemeColor, TnUIBaseStyle, TnUIBaseStyleType } from "@tuniao/tn-ui";
import { AppStorageV2 } from "@kit.ArkUI";
import { TnAppStorageKey } from "@tuniao/tn-ui/src/main/ets/common/storage_key";

@Entry
@ComponentV2
struct ModalCustomColor {
  @Local visible: boolean = false;
  @Local baseStyle: TnUIBaseStyleType = AppStorageV2.connect(TnUIBaseStyle, TnAppStorageKey.BASE_STYLE)!;

  build() {
    Column() {
      Button("自定义按钮颜色")
        .onClick(() => {
          this.visible = true;
        })
      TnModal({
        visible: this.visible,
        $visible: (visible: boolean) => {
          this.visible = visible;
        },
        title: "危险操作",
        content: "此操作不可逆,请谨慎确认。",
        showCancel: true,
        confirmButtonColor: getThemeColor(this.baseStyle, "danger"),
        cancelButtonColor: $r("app.color.tn_text_color_secondary"),
      })
    }
  }
}

遮罩层设置

通过 overlayCloseable 设置点击遮罩层是否关闭模态框,通过 showOverlay 控制是否显示遮罩层。

遮罩层设置

点我查看代码
typescript
// 点击遮罩层可关闭
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "提示",
  content: "点击遮罩层可关闭此模态框",
  overlayCloseable: true,
})

// 不显示遮罩层
TnModal({
  visible: this.visibleNoOverlay,
  $visible: (visible: boolean) => {
    this.visibleNoOverlay = visible;
  },
  title: "无遮罩",
  content: "这个模态框没有遮罩层",
  showOverlay: false,
})

关闭前拦截

通过 beforeClose 属性设置关闭前的拦截回调。回调接收当前操作类型("cancel""confirm"),返回 falsePromise<false> 可阻止模态框关闭。

点我查看代码
typescript
import { TnModal, TnModalAction } from "@tuniao/tn-ui";

// 同步拦截:只允许确认关闭,取消被拦截
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "拦截关闭",
  content: "点击取消将被拦截,只能点击确认关闭。",
  showCancel: true,
  beforeClose: (action: TnModalAction): boolean => {
    if (action === "cancel") {
      return false;
    }
    return true;
  },
})

// 异步拦截:模拟异步请求
TnModal({
  visible: this.visibleAsync,
  $visible: (visible: boolean) => {
    this.visibleAsync = visible;
  },
  title: "异步验证",
  content: "点击确认后将模拟异步请求(1秒),成功后关闭。",
  showCancel: true,
  beforeClose: (action: TnModalAction): Promise<boolean> => {
    return new Promise<boolean>((resolve: Function) => {
      if (action === "confirm") {
        setTimeout(() => {
          resolve(true);
        }, 1000);
      } else {
        resolve(true);
      }
    });
  },
})

文本对齐方式

通过 titleTextAligncontentTextAlign 属性设置标题和内容的文本对齐方式,支持 "left""center""right" 三种方式。

文本对齐方式

点我查看代码
typescript
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "用户协议",
  content: "请仔细阅读并同意我们的用户服务协议和隐私政策。继续使用表示您已同意上述条款。",
  showCancel: true,
  titleTextAlign: "left",
  contentTextAlign: "left",
  cancelText: "不同意",
  confirmText: "同意",
})

自定义宽度和圆角

通过 dialogWidth 属性自定义模态框宽度(单位 vp),通过 dialogBorderRadius 属性自定义圆角(单位 vp)。

自定义宽度和圆角1自定义宽度和圆角2

点我查看代码
typescript
// 自定义宽度
TnModal({
  visible: this.visible,
  $visible: (visible: boolean) => {
    this.visible = visible;
  },
  title: "宽模态框",
  content: "这是一个宽度为 320vp 的模态框",
  dialogWidth: 320,
})

// 自定义圆角
TnModal({
  visible: this.visibleRadius,
  $visible: (visible: boolean) => {
    this.visibleRadius = visible;
  },
  title: "大圆角",
  content: "这是一个圆角为 20vp 的模态框",
  dialogBorderRadius: 20,
})

自定义内容

通过 defaultBuilder 自定义模态框的内容区域,替代默认的 content 文本。

自定义内容

点我查看代码
typescript
import { TnModal, getThemeColor, getFontSizeByKey, TnUIBaseStyle, TnUIBaseStyleType } from "@tuniao/tn-ui";
import { AppStorageV2 } from "@kit.ArkUI";
import { TnAppStorageKey } from "@tuniao/tn-ui/src/main/ets/common/storage_key";

@Entry
@ComponentV2
struct ModalCustomContent {
  @Local visible: boolean = false;
  @Local baseStyle: TnUIBaseStyleType = AppStorageV2.connect(TnUIBaseStyle, TnAppStorageKey.BASE_STYLE)!;

  @Builder
  customContent() {
    Column({ space: "12vp" }) {
      Row({ space: "12vp" }) {
        Column() {
          Text("128")
            .fontSize(getFontSizeByKey(this.baseStyle, "fontSizeXXl"))
            .fontColor(getThemeColor(this.baseStyle, "primary"))
            .fontWeight(FontWeight.Bold)
          Text("积分余额")
            .fontSize(getFontSizeByKey(this.baseStyle, "fontSizeSm"))
            .fontColor($r("app.color.tn_text_color_secondary"))
        }
        .layoutWeight(1)
        .alignItems(HorizontalAlign.Center)

        Column() {
          Text("5")
            .fontSize(getFontSizeByKey(this.baseStyle, "fontSizeXXl"))
            .fontColor(getThemeColor(this.baseStyle, "warning"))
            .fontWeight(FontWeight.Bold)
          Text("优惠券")
            .fontSize(getFontSizeByKey(this.baseStyle, "fontSizeSm"))
            .fontColor($r("app.color.tn_text_color_secondary"))
        }
        .layoutWeight(1)
        .alignItems(HorizontalAlign.Center)
      }
      .width("100%")

      Text("是否使用积分兑换优惠券?")
        .fontSize(getFontSizeByKey(this.baseStyle, "fontSize"))
        .fontColor($r("app.color.tn_text_color_primary"))
        .textAlign(TextAlign.Center)
        .width("100%")
    }
    .width("100%")
  }

  build() {
    Column() {
      Button("自定义内容")
        .onClick(() => {
          this.visible = true;
        })
      TnModal({
        visible: this.visible,
        $visible: (visible: boolean) => {
          this.visible = visible;
        },
        title: "自定义内容",
        showCancel: true,
        defaultBuilder: () => {
          this.customContent();
        },
      })
    }
  }
}

自定义底部按钮

通过 footerBuilder 自定义模态框的底部按钮区域,替代默认的取消/确认按钮。

自定义底部按钮

点我查看代码
typescript
import { TnModal, TnButton, TnUIBaseStyle, TnUIBaseStyleType } from "@tuniao/tn-ui";
import { AppStorageV2 } from "@kit.ArkUI";
import { TnAppStorageKey } from "@tuniao/tn-ui/src/main/ets/common/storage_key";

@Entry
@ComponentV2
struct ModalCustomFooter {
  @Local visible: boolean = false;
  @Local baseStyle: TnUIBaseStyleType = AppStorageV2.connect(TnUIBaseStyle, TnAppStorageKey.BASE_STYLE)!;

  @Builder
  customFooter() {
    Row({ space: "12vp" }) {
      TnButton({
        content: "取消",
        btnSize: "sm",
        plain: true,
        onBtnClick: () => {
          this.visible = false;
        },
      })
      TnButton({
        content: "确认提交",
        btnSize: "sm",
        type: "success",
        onBtnClick: () => {
          this.visible = false;
        },
      })
    }
    .width("100%")
    .justifyContent(FlexAlign.Center)
    .padding({
      left: this.baseStyle.spaceLg,
      right: this.baseStyle.spaceLg,
      top: this.baseStyle.spaceSm,
      bottom: this.baseStyle.spaceLg
    })
  }

  build() {
    Column() {
      Button("自定义底部按钮")
        .onClick(() => {
          this.visible = true;
        })
      TnModal({
        visible: this.visible,
        $visible: (visible: boolean) => {
          this.visible = visible;
        },
        title: "自定义底部",
        content: "底部按钮使用自定义样式",
        footerBuilder: () => {
          this.customFooter();
        },
      })
    }
  }
}

API

Props

参数说明类型默认值
visible是否显示模态框booleanfalse
title模态框标题string-
content模态框内容文本string-
showCancel是否显示取消按钮booleanfalse
cancelText取消按钮文字string"取消"
confirmText确认按钮文字string"确认"
showOverlay是否显示遮罩层booleantrue
overlayCloseable点击遮罩层是否关闭booleanfalse
closeOnBackPress返回键是否关闭booleantrue
dialogWidth弹窗宽度(单位 vp)number280
dialogBorderRadius弹窗圆角(单位 vp),为 0 时使用主题默认圆角number0
titleTextAlign标题文本对齐方式"left" | "center" | "right""center"
contentTextAlign内容文本对齐方式"left" | "center" | "right""center"
confirmButtonColor确认按钮文字颜色ResourceColor主题色
cancelButtonColor取消按钮文字颜色ResourceColor主文字色
confirmButtonBold确认按钮是否加粗booleantrue
beforeClose关闭前拦截回调,返回 false 可阻止关闭(action: TnModalAction) => boolean | Promise<boolean>-

BuilderParams

参数说明类型
defaultBuilder自定义内容区域(覆盖 content 文本)CustomBuilder
titleBuilder自定义标题区域(覆盖 title 文本)CustomBuilder
footerBuilder自定义底部按钮区域(覆盖默认按钮)CustomBuilder

Events

事件名说明回调参数
onConfirm点击确认按钮时触发() => void
onCancel点击取消按钮时触发() => void
onOpen模态框打开时触发() => void
onClose模态框关闭时触发() => void
$visible模态框显示状态变化(双向绑定)(visible: boolean) => void

类型定义

TnModalAction

typescript
type TnModalAction = "cancel" | "confirm";

TnModalTextAlign

typescript
type TnModalTextAlign = "left" | "center" | "right";

TnModalBeforeClose

typescript
type TnModalBeforeClose = (action: TnModalAction) => boolean | Promise<boolean>;