@shivip/mp-core 工具参考
@shivip/mp-core 是公司内部面向 Vue 3、uni-app 和微信小程序项目的基础工具包。自 @hfyidu/api@1.0.1 起,其公开成员由 @hfyidu/api/core 转发。
import { Future, ModuleUseCase, createSingleton } from '@hfyidu/api/core'业务项目不需要、也不应额外安装 @shivip/mp-core。
响应式模块用例
ModuleUseCase<Params, Response>
在 BaseUseCase 基础上增加 Vue 响应式执行状态和错误信息,适合页面初始化、详情加载、提交操作等单次异步任务。
公开状态:
| 成员 | 类型 | 功能 |
|---|---|---|
status | ShallowRef<ModuleUseCaseStatus | null> | 当前运行状态 |
error | string | null | 捕获后的错误信息 |
data | UseCaseResponse<Response> | 最近一次成功结果及更新时间 |
run(params) | Promise<UseCaseResponse<Response>> | 执行用例 |
ModuleUseCase.from(fn) | 静态工厂 | 将 Promise 函数快速包装成模块用例 |
ModuleUseCaseStatus 包含:
running:正在执行success:执行成功failure:执行失败
import { ModuleUseCase, ModuleUseCaseStatus } from '@hfyidu/api/core'
interface Profile {
id: number
nickname: string
}
const profileCase = ModuleUseCase.from<null, Profile>(
() =>
new Promise((resolve, reject) => {
uni.request({
url: '/api/profile',
success: ({ data }) => resolve(data as Profile),
fail: reject,
})
}),
)
await profileCase.run(null)
if (profileCase.status.value === ModuleUseCaseStatus.success) {
console.log(profileCase.data.data)
}
if (profileCase.status.value === ModuleUseCaseStatus.failure) {
console.error(profileCase.error)
}错误处理
ModuleUseCase 会捕获 onRun 抛出的错误并写入 error,状态改为 failure。调用方应观察状态或检查 error,不能只依赖外层 catch。
useModuleData(useCase, defaultValue?)
把 ModuleUseCase.data.data 映射为 Vue Ref。当用例状态变为 success 时,Ref 自动更新。
import { ModuleUseCase, useModuleData } from '@hfyidu/api/core'
const countCase = ModuleUseCase.from(async () => {
const { data } = await uni.request<{ count: number }>({ url: '/api/count' })
return data.count
})
const count = useModuleData(countCase, 0)
await countCase.run(null)
console.log(count.value)分页用例
PaginatorUseCase<Params, ItemDto, Response>
统一管理分页请求、列表拼接和加载状态。子类只需实现 onRun(params)。
| 成员 | 功能 |
|---|---|
list | 当前累计列表 |
currentPage | 当前页码,初始为 1 |
pageSize | 每页数量,默认从过滤参数读取,否则为 15 |
refreshing | 是否正在刷新 |
hasMore | 是否可能还有下一页 |
loadedCount | 已加载条目数量 |
isEmpty | 首次加载后列表是否为空 |
error | 最近一次分页错误文本 |
extra | 响应中除 list 外的附加字段 |
refresh() | 清空状态并重新加载当前初始页 |
loadCurrentPage() | 尚未加载时触发刷新 |
loadNextPage() | hasMore 为真时加载下一页 |
loadPrevPage() | 尝试加载上一页 |
insertAt(item, index?) | 插入一条本地数据 |
removeAt(index) | 删除一条本地数据 |
loadPrevPage() 的 1.0.1 已知限制
当前内联版本的 loadPrevPage() 包含恒真保护条件,调用后会直接返回,不会发起上一页请求。业务代码暂时不要依赖该方法;向前分页场景应等待内部工具包修复并由 @hfyidu/api 后续版本重新打包。
相关类型:
type PagedResultDto<T> = {
list: T[]
}
interface PagedQueryParams {
currentPage: number
pageSize: number
}
interface PaginationUseCaseConfigOption {
currentPage: number
pageSize: number
makeParams(query: Record<string, any>): Record<string, any>
}实际用法:
import { PaginatorUseCase, type PagedResultDto } from '@hfyidu/api/core'
interface Message {
id: number
content: string
}
interface MessageQuery {
page?: number
limit?: number
type?: string
}
class MessageListUseCase extends PaginatorUseCase<
MessageQuery,
Message,
PagedResultDto<Message>
> {
protected async onRun(params: MessageQuery) {
const { data } = await uni.request<PagedResultDto<Message>>({
url: '/api/messages',
data: params,
})
return data
}
}
// 分页用例必须只创建一次并复用,不能每次渲染都 new。
const messages = new MessageListUseCase()
await messages.refresh()
await messages.loadNextPage()
console.log(messages.list)
console.log(messages.refreshing.value, messages.hasMore.value)usePaginatorData(useCase)
返回一个指向分页列表初始值的 Vue Ref:
import { usePaginatorData } from '@hfyidu/api/core'
const list = usePaginatorData(messages)
console.log(list.value)使用建议
当前业务 SDK 的页面更适合直接读取 useCase.list、refreshing.value 和 hasMore.value。分页过程中 PaginatorUseCase 可能替换 list 数组引用,使用 usePaginatorData 前应确认它是否符合页面的响应式更新方式。
业务枚举
BaseEnumeration
用于定义同时拥有数值、代码和展示文本的类型安全业务枚举。
import { BaseEnumeration } from '@hfyidu/api/core'
class PayStatus extends BaseEnumeration {
static readonly pending = new PayStatus(0, 'pending', '待支付')
static readonly paid = new PayStatus(1, 'paid', '已支付')
static readonly closed = new PayStatus(2, 'closed', '已关闭')
}
PayStatus.find(1) // PayStatus.paid
PayStatus.find('paid') // PayStatus.paid
PayStatus.find('unknown') // null
PayStatus.values() // 全部枚举成员
PayStatus.keys() // ['pending', 'paid', 'closed']
PayStatus.paid.toString() // 'paid'
PayStatus.paid.valueOf() // 1
PayStatus.paid.containOf(PayStatus.paid, PayStatus.closed) // true单例与全局容器
createSingleton(Class)
使用 Proxy 保证同一个类无论 new 多少次都返回同一实例。
import { createSingleton } from '@hfyidu/api/core'
class AudioManagerImpl {
volume = 1
}
const AudioManager = createSingleton(AudioManagerImpl)
const first = new AudioManager()
const second = new AudioManager()
console.log(first === second) // true
first.volume = 0.5
console.log(second.volume) // 0.5代理类还提供内部的 destroy() 能力以清除缓存,但该成员未体现在当前公开 TypeScript 返回类型中。业务代码通常应让单例随应用生命周期存在。
Container
在 globalThis 上按字符串或 Symbol 保存共享对象。
| 方法 | 功能 |
|---|---|
Container.put(key, value) | 写入或覆盖全局值 |
Container.find<T>(key) | 查找全局值,不存在时返回 undefined |
Container.secureGet(key, defaultValue?) | 不存在时写入默认值,再返回同一对象 |
import { Container } from '@hfyidu/api/core'
const APP_CONFIG = Symbol.for('company.app.config')
const config = Container.secureGet(APP_CONFIG, {
apiBaseUrl: 'https://api.example.com',
})
Container.put('currentTenant', 'tenant-a')
const tenant = Container.find<string>('currentTenant')命名空间
Container 写入的是全局对象。key 应使用公司/项目命名空间或 Symbol.for(),避免与页面脚本、第三方库产生冲突;不要存放 token、密码等敏感信息。
createSingletonWithContainer(Class)
返回一个 getter,首次调用时创建对象,之后从 Container 返回同一实例。类需要提供稳定的静态 mark。
import { createSingletonWithContainer } from '@hfyidu/api/core'
class AnalyticsService {
static mark = 'analytics-service'
report(event: string) {
console.log('report:', event)
}
}
const useAnalytics = createSingletonWithContainer(AnalyticsService)
useAnalytics().report('page_view')
console.log(useAnalytics() === useAnalytics()) // true异步工具
Future.delayed(duration, handler?)
延迟指定毫秒数,可选在延迟结束后执行函数并返回结果。
import { Future } from '@hfyidu/api/core'
await Future.delayed(300)
const timestamp = await Future.delayed(300, () => Date.now())如果回调抛错,返回的 Promise 会 reject。
Future.completer(handler, option?)
把带 success、fail 回调的 uni-app API 转为 Promise。
import { Future } from '@hfyidu/api/core'
const systemInfo = await Future.completer(uni.getSystemInfo)
await Future.completer(uni.setStorage, {
key: 'theme',
data: 'dark',
})
const value = await Future.completer(uni.getStorage, {
key: 'theme',
})option 中无需传入 success、fail 或 complete,工具会自动注入成功和失败回调。
通用类型
HigherOrderComponent<T>
描述“接收组件选项并返回组件选项”的高阶组件函数:
import type { HigherOrderComponent } from '@hfyidu/api/core'
interface PageOptions {
title: string
}
const withDefaultTitle: HigherOrderComponent<PageOptions> = option => ({
title: option.title || '默认标题',
})CallbackHandler
通用回调函数类型:
import type { CallbackHandler } from '@hfyidu/api/core'
const callbacks: CallbackHandler[] = []
callbacks.push((payload: unknown) => console.log(payload))