# oopsoh **Repository Path**: im76ix/oopsoh ## Basic Information - **Project Name**: oopsoh - **Description**: 一个面向 uni-app 的轻量交互工具库,用来优雅处理页面里常见的提示、跳转、确认弹窗、加载态和防重复提交。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-04-17 - **Last Updated**: 2026-05-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # oopsoh 一个面向 `uni-app` 的轻量交互工具库,用来优雅处理页面里常见的提示、跳转、确认弹窗、加载态和防重复提交。 > GitHub: https://github.com/im76ix/oopsoh > Gitee: https://gitee.com/im76ix/oopsoh ## 为什么需要 oopsoh 相信经常使用 `uni-app` 的同学都遇到过这个问题:提交表单成功后,想先给用户一个成功提示,再跳转到下一个页面。 但如果直接这样写: ```ts uni.showToast({ title: "保存成功", duration: 1500, }) uni.navigateTo({ url: "/pages/list/index", }) ``` 页面会立刻跳走,提示几乎一闪而过。因为 `uni.showToast` 是异步展示的,它不会阻塞后面的跳转逻辑。 通常我们会手动加 `setTimeout`: ```ts uni.showToast({ title: "保存成功", duration: 1500, }) setTimeout(() => { uni.navigateTo({ url: "/pages/list/index", }) }, 1500) ``` 可以用,但不够优雅,也很容易在项目里重复出现。 `oopsoh` 就是为了解决这些页面交互小流程而生。 ## 安装 ```bash npm i oopsoh ``` 或: ```bash pnpm add oopsoh ``` ## 导入方式 `oopsoh` 同时支持命名空间写法和函数式写法。 ### 推荐写法 ```ts import oh from "oopsoh" oh.success("保存成功") oh.to("保存成功", "/pages/list/index") ``` ### 函数式写法 ```ts import { toast, confirm, withLoading } from "oopsoh" toast("hello world") await confirm("确定删除吗?") await withLoading("提交中", submit) ``` ### 兼容旧写法 旧版本的 `oh(msg, options, callback)` 仍然可以继续使用。 ```ts import { oh } from "oopsoh" oh("保存成功", { ico: "success" }, () => { uni.navigateTo({ url: "/pages/list/index", }) }) ``` ## 快速开始 ### 简单提示 ```ts oh.toast("hello world") ``` 也可以直接调用 `oh`,效果等同于 `oh.toast`: ```ts oh("hello world") ``` 函数式写法: ```ts import { toast } from "oopsoh" toast("hello world") ``` ### 成功提示 ```ts oh.success("保存成功") ``` 等同于: ```ts oh.toast("保存成功", { icon: "success" }) ``` ### 失败提示 ```ts oh.error("提交失败") ``` ### 加载提示 这是基于 `uni.showToast` 的 loading 图标提示,适合短时间反馈。 ```ts oh.loading("加载中") ``` 如果是异步任务的全局加载态,建议使用 `oh.withLoading`。 ## 提示后跳转 ### navigateTo 跳转到非 `tabBar` 页面。 ```ts oh.to("/pages/detail/index") ``` 提示完成后再跳转: ```ts oh.to("保存成功", "/pages/list/index", { icon: "success", duration: 1500, }) ``` 传递 `uni.navigateTo` 原生参数: ```ts oh.to("保存成功", "/pages/list/index", { icon: "success", route: { animationType: "pop-in", animationDuration: 300, }, }) ``` ### redirectTo 关闭当前页面并跳转。 ```ts oh.redirect("/pages/result/index") ``` 提示完成后再跳转: ```ts oh.redirect("提交成功", "/pages/result/index", { icon: "success", }) ``` ### reLaunch 关闭所有页面并打开某个页面,常用于登录过期、切换身份、回到首页等场景。 ```ts oh.reLaunch("登录已过期", "/pages/login/index", { icon: "none", }) ``` ### switchTab 跳转到 `tabBar` 页面。 ```ts oh.tab("/pages/home/index") ``` 提示完成后跳转到 `tabBar` 页面: ```ts oh.tab("发布成功", "/pages/home/index", { icon: "success", }) ``` ### navigateBack 直接返回上一页: ```ts oh.back() ``` 返回指定层级: ```ts oh.back(2) ``` 提示完成后再返回: ```ts oh.back("保存成功", { icon: "success", delta: 1, }) ``` ## 确认弹窗 `oh.confirm` 基于 `uni.showModal` 封装,用户点击确认时执行回调并返回 `true`,取消时返回 `false`。 ```ts const ok = await oh.confirm("确定删除这条数据吗?") if (ok) { await deleteItem() } ``` 也可以把确认后的逻辑直接交给它: ```ts await oh.confirm("确定删除这条数据吗?", async () => { await deleteItem() oh.success("删除成功") }) ``` 自定义按钮文案: ```ts await oh.confirm( "删除后不可恢复,确定继续吗?", deleteItem, { title: "删除确认", confirmText: "删除", cancelText: "再想想", confirmColor: "#e54d42", }, ) ``` 函数式写法: ```ts import { confirm } from "oopsoh" await confirm("确定退出登录吗?", logout) ``` ## 加载态包裹异步任务 `oh.withLoading` 会自动调用 `uni.showLoading` 和 `uni.hideLoading`。不论任务成功还是失败,都会在结束时关闭 loading。 ```ts await oh.withLoading("提交中", async () => { await submitForm() }) ``` 获取任务返回值: ```ts const user = await oh.withLoading("加载用户信息", async () => { return await getUserInfo() }) ``` 关闭透明蒙层: ```ts await oh.withLoading( "加载中", loadData, { mask: false, }, ) ``` 函数式写法: ```ts import { withLoading } from "oopsoh" await withLoading("保存中", saveData) ``` ## 防重复提交 `oh.lock` 可以给函数加运行锁,防止按钮连点造成重复提交。 ```ts const submitOnce = oh.lock(async () => { await submitForm() oh.success("提交成功") }) submitOnce() ``` 重复触发时给用户提示: ```ts const submitOnce = oh.lock(submitForm, { message: "正在提交,请稍候", }) ``` 任务结束后延迟解锁: ```ts const payOnce = oh.lock(createPayOrder, { message: "支付处理中", delay: 1000, }) ``` 在 Vue 页面中使用: ```vue ``` ## API 总览 ### oh / toast ```ts oh(msg: string, options?: ToastOptions, callback?: () => void): void oh.toast(msg: string, options?: ToastOptions, callback?: () => void): void toast(msg: string, options?: ToastOptions, callback?: () => void): void ``` 显示普通提示。`callback` 会在提示展示时长结束后执行。 ### success ```ts oh.success(msg: string, options?: ToastOptions, callback?: () => void): void ``` 显示成功提示,默认 `icon` 为 `success`。 ### error ```ts oh.error(msg: string, options?: ToastOptions, callback?: () => void): void ``` 显示失败提示,默认 `icon` 为 `error`。 ### loading ```ts oh.loading(msg?: string, options?: ToastOptions, callback?: () => void): void ``` 显示 loading 类型的 Toast,默认文案为 `加载中`。 ### confirm ```ts oh.confirm( content: string, onConfirm?: () => void | Promise, options?: ConfirmOptions, ): Promise ``` 显示确认弹窗。确认返回 `true`,取消返回 `false`。 ### to ```ts oh.to(url: string, options?: NavigateOptions): void oh.to(msg: string, url: string, options?: ToastRouteOptions): void ``` 跳转到非 `tabBar` 页面,对应 `uni.navigateTo`。 ### redirect ```ts oh.redirect(url: string, options?: RedirectOptions): void oh.redirect(msg: string, url: string, options?: ToastRouteOptions): void ``` 关闭当前页面并跳转,对应 `uni.redirectTo`。 ### reLaunch ```ts oh.reLaunch(url: string, options?: ReLaunchOptions): void oh.reLaunch(msg: string, url: string, options?: ToastRouteOptions): void ``` 关闭所有页面并跳转,对应 `uni.reLaunch`。 ### tab ```ts oh.tab(url: string, options?: SwitchTabOptions): void oh.tab(msg: string, url: string, options?: ToastRouteOptions): void ``` 跳转到 `tabBar` 页面,对应 `uni.switchTab`。 ### back ```ts oh.back(delta?: number): void oh.back(msg: string, options?: BackOptions): void ``` 返回上一页或指定层级,对应 `uni.navigateBack`。 ### withLoading ```ts oh.withLoading( title: string, task: () => T | Promise, options?: LoadingOptions, ): Promise ``` 用 `uni.showLoading` 包裹一个同步或异步任务,并自动关闭 loading。 ### lock ```ts oh.lock( task: (...args: Args) => Result | Promise, options?: LockOptions, ): (...args: Args) => Promise ``` 给函数增加运行锁,防止重复点击、重复提交。 ## 参数说明 ### ToastOptions | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `icon` | `"success" \| "error" \| "loading" \| "none"` | `"none"` | Toast 图标 | | `ico` | `"success" \| "error" \| "loading" \| "none"` | - | 兼容旧版本字段,等同于 `icon` | | `duration` | `number` | `1500` | 提示展示时长,单位 ms | | `mask` | `boolean` | `false` | 是否显示透明蒙层 | | `image` | `string` | - | 自定义图标图片路径 | | `success` | `UniApp.ShowToastOptions["success"]` | - | `uni.showToast` 原生成功回调 | | `fail` | `UniApp.ShowToastOptions["fail"]` | - | `uni.showToast` 原生失败回调 | | `complete` | `UniApp.ShowToastOptions["complete"]` | - | `uni.showToast` 原生完成回调 | ### ToastRouteOptions `ToastRouteOptions` 继承 `ToastOptions`,额外支持: | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `route` | `object` | - | 传给原生跳转 API 的参数,不包含 `url` | 示例: ```ts oh.to("保存成功", "/pages/list/index", { icon: "success", route: { animationType: "pop-in", }, }) ``` ### ConfirmOptions | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `title` | `string` | `"提示"` | 弹窗标题 | | `confirmText` | `string` | `"确定"` | 确认按钮文案 | | `cancelText` | `string` | `"取消"` | 取消按钮文案 | | `showCancel` | `boolean` | `true` | 是否显示取消按钮 | | `confirmColor` | `string` | - | 确认按钮颜色 | | `cancelColor` | `string` | - | 取消按钮颜色 | | `success` | `UniApp.ShowModalOptions["success"]` | - | `uni.showModal` 原生成功回调 | | `fail` | `UniApp.ShowModalOptions["fail"]` | - | `uni.showModal` 原生失败回调 | | `complete` | `UniApp.ShowModalOptions["complete"]` | - | `uni.showModal` 原生完成回调 | ### BackOptions | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `delta` | `number` | `1` | 返回的页面层数 | `BackOptions` 同时继承 `ToastOptions`,所以也可以传入 `icon`、`duration`、`mask` 等提示参数。 ### LoadingOptions | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `mask` | `boolean` | `true` | 是否显示透明蒙层 | ### LockOptions | 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `message` | `string` | - | 重复触发时的提示文案 | | `delay` | `number` | `0` | 任务结束后延迟多久解锁,单位 ms | | `onLocked` | `() => void` | - | 重复触发时的自定义处理 | ## 完整示例 ```ts import oh from "oopsoh" const submit = oh.lock(async () => { await oh.withLoading("提交中", async () => { // await api.submitForm() }) oh.to("提交成功", "/pages/list/index", { icon: "success", duration: 1500, }) }, { message: "正在提交,请勿重复点击", }) ``` ## TypeScript `oopsoh` 自带类型声明,安装后即可获得类型提示。 ```ts import type { ToastOptions, ConfirmOptions, ToastRouteOptions, LockOptions, } from "oopsoh" ``` 旧版本的 `OhOptions` 类型仍然保留: ```ts import type { OhOptions } from "oopsoh" ``` ## 兼容说明 - 保留 `oh("提示", options, callback)` 旧写法。 - 保留 `ico` 字段,推荐新项目使用 `icon`。 - 新增默认导出 `oh`,推荐 `import oh from "oopsoh"`。 - 新增具名函数导出,支持按需导入。 ## 建议与反馈 如果你在使用过程中有更好的想法,欢迎在 GitHub 或 Gitee 提 issue。 如果这个小库刚好帮你少写了一点重复代码,也欢迎点个 Star。