# 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。