基础示例
基本用法
最基本的用法是传入一个返Promise 的异步函数
vue
<template>
<div>
<button @click="run">获取用户信息</button>
<div v-if="loading">加载..</div>
<div v-else-if="error">错误: {{ error.message }}</div>
<div v-else>
<p>用户 {{ data?.name }}</p>
<p>邮箱: {{ data?.email }}</p>
</div>
</div>
</template>
<script setup>
import useRequest from '@pluve/use-request-vue';
const { data, loading, error, run } = useRequest(() => fetch('/api/user/1').then((res) => res.json()));
</script>带参数的请求
vue
<template>
<div>
<input v-model="userId" placeholder="输入用户ID" />
<button @click="() => run(userId)">获取用户信息</button>
<div v-if="loading">加载..</div>
<div v-else-if="error">错误: {{ error.message }}</div>
<div v-else>{{ data }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import useRequest from '@pluve/use-request-vue';
const userId = ref('1');
const { data, loading, error, run } = useRequest((id) => fetch(`/api/user/${id}`).then((res) => res.json()), {
manual: true, // 手动触发请求
});
</script>使用插件的完整示
vue
<template>
<div>
<input
v-model="keyword"
@input="handleSearch"
placeholder="搜索..."
/>
<div v-if="loading">
搜索..{{ retryCount ? `(${retryCount} 次重` : '' }}
</div>
<div v-else-if="error">
错误: {{ error.message }}
<button @click="run(keyword)">重试</button>
</div>
<div v-else>
<div v-for="item in data?.list" :key="item.id" class="item">
{{ item.name }}
</div>
<div v-if="data?.list.length === 0">
没有找到相关结果
</div>
</div>
<div v-if="!loading && data?.list?.length > 0" class="pagination">
<button
:disabled="pagination.page <= 1"
@click="prevPage"
>
上一 </button>
<span>{{ pagination.page }} /span>
<button
:disabled="!data?.hasMore"
@click="nextPage"
>
下一 </button>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import useRequest from '@pluve/use-request-vue';
import {
useDebouncePlugin,
useRetryPlugin,
useCachePlugin
} from '@pluve/use-request-vue';
const keyword = ref('');
const pagination = reactive({
page: 1,
pageSize: 10,
});
const {
data,
loading,
error,
run,
retryCount,
params: [currentKeyword = '']
} = useRequest(
(kw, page = 1, pageSize = 10) => {
const url = `/api/search?q=${encodeURIComponent(kw)}&page=${page}&pageSize=${pageSize}`;
return fetch(url).then(res => {
if (!res.ok) throw new Error('请求失败');
return res.json();
});
},
{
manual: true,
debounceInterval: 500,
cacheKey: 'search-cache',
retryCount: 3,
onSuccess: (result) => {
console.log('搜索成功:', result);
},
onError: (e) => {
console.error('搜索失败:', e);
},
},
[
useDebouncePlugin(),
useRetryPlugin(),
useCachePlugin({
cacheTime: 5 * 60 * 1000, // 5分钟
}),
]
);
// 搜索处理
const handleSearch = () => {
if (!keyword.value.trim()) return;
pagination.page = 1; // 重置为第一 run(keyword.value, 1, pagination.pageSize);
};
// 上一const prevPage = () => {
if (pagination.page <= 1) return;
pagination.page--;
run(keyword.value || currentKeyword, pagination.page, pagination.pageSize);
};
// 下一const nextPage = () => {
if (!data.value?.hasMore) return;
pagination.page++;
run(keyword.value || currentKeyword, pagination.page, pagination.pageSize);
};
// 初始加载
// run('', 1, pagination.pageSize);
</script>
<style scoped>
input {
padding: 8px 12px;
margin-right: 8px;
border: 1px solid #ddd;
border-radius: 4px;
width: 200px;
}
button {
padding: 8px 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 0 4px;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.item {
padding: 12px;
border-bottom: 1px solid #eee;
}
.item:hover {
background-color: #f5f5f5;
}
.pagination {
margin-top: 20px;
display: flex;
align-items: center;
gap: 12px;
}
</style>Vue Router 集成
vue
<template>
<div>
<h1>用户详情</h1>
<div v-if="loading">加载..</div>
<div v-else-if="error">
加载失败: {{ error.message }}
<button @click="retry">重试</button>
</div>
<div v-else>
<h2>{{ user.name }}</h2>
<p>邮箱: {{ user.email }}</p>
<p>电话: {{ user.phone }}</p>
</div>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
import useRequest from '@pluve/use-request-vue';
import { useRetryPlugin } from '@pluve/use-request-vue';
const route = useRoute();
const userId = computed(() => route.params.id);
const {
data: user,
loading,
error,
retry,
} = useRequest(
(id) => fetch(`/api/users/${id}`).then(res => {
if (!res.ok) throw new Error('用户不存);
return res.json();
}),
{
refreshDeps: [userId], // userId 变化时重新请 retryCount: 3,
},
[useRetryPlugin()]
);
// 也可以使watch 监听路由参数变化
// watch(() => route.params.id, (newId) => {
// if (newId) {
// run(newId);
// }
// }, { immediate: true });
</script>Pinia 集成
typescript
// stores/user.js
import { defineStore } from 'pinia';
import useRequest from '@pluve/use-request-vue';
export const useUserStore = defineStore('user', () => {
const {
data: user,
loading,
error,
run: fetchUser,
} = useRequest((id) => fetch(`/api/users/${id}`).then((res) => res.json()), {
manual: true,
initialData: null,
});
return {
user,
loading,
error,
fetchUser,
};
});vue
<!-- UserProfile.vue -->
<template>
<div>
<button @click="loadUser">加载用户</button>
<div v-if="loading">加载..</div>
<div v-else-if="error">错误: {{ error.message }}</div>
<div v-else-if="user">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
</div>
</div>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import { useUserStore } from './stores/user';
const userStore = useUserStore();
const { user, loading, error } = storeToRefs(userStore);
const { fetchUser } = userStore;
const loadUser = () => {
fetchUser(1);
};
</script>