npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-model-lite

v0.5.0

Published

轻量级 Vue 3 数据请求与状态管理库,提供三个核心 API:`fetcher`、`useFetch` 和 `createModel`。

Readme

vue-model-lite

轻量级 Vue 3 数据请求与状态管理库,提供三个核心 API:fetcheruseFetchcreateModel

安装

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