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