vue-model-lite
v0.5.0
Published
轻量级 Vue 3 数据请求与状态管理库,提供三个核心 API:`fetcher`、`useFetch` 和 `createModel`。
Readme
vue-model-lite
轻量级 Vue 3 数据请求与状态管理库,提供三个核心 API:fetcher、useFetch 和 createModel。
安装
npm install vue-model-lite
# 或
pnpm add vue-model-lite需要 Vue >= 3.2.0 作为 peer dependency。
API
fetcher
基于原生 fetch 封装的 HTTP 客户端,支持快捷方法、拦截器和全局配置。
基本用法
import { fetcher } from 'vue-model-lite';
// GET 请求
const res = await fetcher.get<UserList>('/api/users');
console.log(res.data);
// POST 请求
const res = await fetcher.post('/api/users', {
data: { name: 'Tom', age: 18 },
});
// 其他方法:put、patch、delete、head、options
await fetcher.put('/api/users/1', { data: { name: 'Jerry' } });
await fetcher.delete('/api/users/1');全局配置
fetcher.config({
base: 'https://api.example.com',
timeout: 5000,
headers: {
Authorization: 'Bearer token',
},
});创建独立实例
const api = fetcher.create({
base: 'https://other-api.example.com',
timeout: 10000,
headers: { 'X-Custom': 'value' },
});
await api.get('/data');请求配置项
| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| url | string | - | 请求地址 |
| base | string | '' | 基础路径,拼接在 url 前 |
| method | string | 'get' | 'get' \| 'post' \| 'put' \| 'patch' \| 'delete' \| 'head' \| 'options' |
| data | object | - | 请求参数,GET 拼到 URL,POST 放 body |
| timeout | number | 0 | 超时时间(ms),0 表示不超时 |
| headers | Record<string, string> | {} | 请求头 |
| credentials | string | 'same-origin' | 'same-origin' \| 'omit' \| 'include' |
| requestType | string | 'json' | 'json' \| 'form' |
| responseType | string | 'json' | 'json' \| 'text' \| 'stream' |
| validateStatus | (status) => boolean | status >= 200 && < 300 | 自定义状态码校验 |
| transformUrl | Function[] | [] | URL 转换管道 |
| transformRequest | Function[] | [] | 请求数据转换管道 |
| transformResponse | Function[] | [] | 响应数据转换管道 |
响应结构
interface FetchResponse<R> {
ok?: boolean;
status?: number;
statusText?: string;
headers?: Headers;
type?: ResponseType;
url?: string;
data?: R;
}useFetch
Vue 3 组合式 API,在组件中发起请求并自动管理 loading / data / error 状态。
基本用法
<script setup lang="ts">
import { useFetch } from 'vue-model-lite';
// 传入 URL,自动发起 GET 请求
const { data, loading, error } = useFetch('/api/users');
</script>
<template>
<div v-if="loading">加载中...</div>
<div v-else-if="error">{{ error.message }}</div>
<div v-else>{{ data }}</div>
</template>配置对象写法
const { data, loading, fetch, cancel } = useFetch({
url: '/api/users',
method: 'post',
data: { page: 1 },
auto: false, // 不自动请求,需手动调用 fetch()
timeout: 5000,
});
// 手动触发
await fetch();
// 带参数触发
await fetch({ page: 2 });Promise 写法
import { fetcher, useFetch } from 'vue-model-lite';
// 传入返回 Promise 的函数
const { data, loading } = useFetch(() => fetcher.get('/api/users'));
// 或通过 promise 选项
const { data } = useFetch({
promise: () => fetch('/api/data').then(r => r.json()),
auto: true,
});轮询
import { ref } from 'vue';
// 固定间隔轮询
const { data, cancel } = useFetch({
url: '/api/status',
pollingInterval: 3000, // 每 3 秒
});
// 响应式间隔(修改 interval.value 自动生效)
const interval = ref(3000);
const { data } = useFetch({
url: '/api/status',
pollingInterval: interval,
});
cancel(); // 停止轮询监听数据源
import { ref } from 'vue';
const keyword = ref('');
// keyword 变化时自动重新请求
const { data } = useFetch({
url: '/api/search',
data: () => ({ keyword: keyword.value }),
watch: keyword,
});跳过请求
const { data, fetch } = useFetch({
url: '/api/users',
skip: () => !isLoggedIn.value, // 条件不满足时跳过
});加载更多
const page = ref(1);
const { data, loadmore } = useFetch({
url: '/api/list',
data: () => ({ page: page.value }),
loadmoreField: 'items', // 新数据追加到 data.items 数组
});
// 加载下一页
page.value++;
await loadmore({ page: page.value });事件回调
const { onData, onError, onFinish } = useFetch('/api/users');
onData((data) => console.log('成功:', data));
onError((error) => console.log('失败:', error));
onFinish((data, error) => console.log('完成'));等待首次请求
const { firstFetch, data } = useFetch('/api/config');
// 等待第一次请求完成(适用于初始化场景)
const { data: result, error } = await firstFetch;返回值一览
| 字段 | 类型 | 说明 |
|------|------|------|
| data | Ref<R \| null> | 响应数据 |
| loading | Ref<boolean> | 是否正在请求 |
| error | Ref<Error \| null> | 错误信息 |
| state | { data, loading, error } | 状态集合(reactive) |
| fetch(data?) | (P?) => Promise<R> | 手动发起请求 |
| refetch(data?) | (P?) => Promise<R> | 静默重新请求(不触发 loading) |
| cancel() | () => void | 取消请求 / 停止轮询 |
| polling(ms?) | (number?) => void | 手动启动轮询 |
| loadmore(data?) | (P?) => void | 加载更多 |
| action | object | 所有方法的集合 |
| onData | (fn) => unsubscribe | 数据返回回调 |
| onError | (fn) => unsubscribe | 错误回调 |
| onFinish | (fn) => unsubscribe | 完成回调 |
| event | object | 所有事件的集合 |
| firstFetch | Promise<{ data?, error? }> | 第一次请求的 Promise |
配置项
| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| url | string \| () => string | - | 请求地址,支持函数 |
| promise | () => Promise | - | 自定义 Promise(与 url 二选一) |
| auto | boolean | true | 是否自动发起请求 |
| pollingInterval | number \| Ref<number> | 0 | 轮询间隔(ms),0 不轮询 |
| watch | Ref \| Ref[] | null | 监听数据源,变化时自动请求 |
| skip | boolean \| () => boolean | false | 跳过请求 |
| loadmoreField | string | '' | loadmore 数组字段路径 |
| fetcher | Fetcher | 全局 fetcher | 自定义 fetcher 实例 |
| 其他 | - | - | 继承 fetcher 所有配置项 |
createModel
跨组件共享响应式状态的工厂函数。同一个函数引用始终返回同一个 reactive 实例(单例)。
基本用法
// models/user.ts
import { ref } from 'vue';
import { createModel, useFetch } from 'vue-model-lite';
function userModel() {
const name = ref('');
const age = ref(0);
const { data, loading, fetch: fetchUser } = useFetch({
url: '/api/user',
auto: false,
});
return { name, age, data, loading, fetchUser };
}
export default () => createModel(userModel);<!-- ComponentA.vue -->
<script setup>
import useUserModel from '@/models/user';
const { name, fetchUser } = useUserModel();
await fetchUser();
</script>
<!-- ComponentB.vue — 共享同一份数据 -->
<script setup>
import useUserModel from '@/models/user';
const { name, data } = useUserModel();
// name 和 data 与 ComponentA 完全同步
</script>要点
- 传入函数必须返回普通对象,返回值会被
reactive()包裹 - 单例模式:相同函数引用返回同一实例,不同函数返回不同实例
- 可在 model 内部使用
useFetch,请求状态自动跨组件共享 - 适合管理全局状态(用户信息、配置、购物车等)
TypeScript 支持
所有 API 支持泛型:
interface User {
id: number;
name: string;
}
// fetcher
const res = await fetcher.get<User>('/api/user/1');
res.data; // User
// useFetch
const { data } = useFetch<User>('/api/user/1');
data.value; // User | null
// 带请求参数类型
const { fetch } = useFetch<User, { id: number }>({
url: '/api/user',
auto: false,
});
await fetch({ id: 1 });License
MIT
