English | 简体中文
Vue composables for fetching data, based on unjs/ofetch.
$ pnpm i vfetcher
- Carefully designed API: Intentionally mimicking the nuxt/useFetch API to maintain consistency as much as possible and reduce migration burden.
- More features: Throttling/debouncing/polling/pagination out of the box... and more features to come!
Visit examples to see the config examples, visit test to see the usage examples.
vfetcher
re-export all exports of ofetch
so you can directly use ofetch:
import { $fetch } from 'vfetcher/ofetch'
The first parameter of useAsyncData
is a callback function, and the second parameter is its configuration object. By default, the callback is automatically called during initialization:
import { useAsyncData } from 'vfetcher'
const { data } = useAsyncData(() => $fetch('/return-ok'))
watchEffect(() => {
console.log(data.value) // Ref
// -> null
// -> 'ok'
})
Use the immediate: false
option to prevent the request from being sent automatically during initialization:
const { data, execute, refresh } = useAsyncData(() => $fetch('return-ok'), {
immediate: false
})
watchEffect(() => {
console.log(data.value)
})
// -> null
// await refresh() // as alias of execute
await execute()
// -> 'ok'
The watch
option accepts the same values as the first parameter of Vue's watch
. When these reactive variables change, a request will be automatically sent:
const dep = ref('foo')
useAsyncData(() => $fetch('ok'), {
watch: [dep]
})
// request to => 'ok'
dep.value = 'bar'
// request to => 'ok'
The ready
option accepts a reactive boolean value or a function that returns a boolean. A request is only sent when the result is true; if the result is false, the execute
is terminated immediately, and no request is sent. This is useful when using dependent requests with specific conditions:
const ready = ref(false)
const { execute } = useAsyncData(() => $fetch('ok'), {
immediate: false,
ready
})
await execute()
// the promise will be resolved immediately and no request will be sent
ready.value = true
await execute()
// request to => 'ok'
The status
return value of useAsyncData
indicates the current state. By monitoring the status
, you can implement callbacks in different situations. The status
is initially idle
, indicating an idle state; it changes to pending
before the request is sent, indicating a waiting response. Upon successful request, it changes to success
, indicating success, or to error
if the request fails:
const { status } = useAsyncData(() => $fetch('ok'))
// Equivalent to `onSuccess` hook:
watch(status, (v) => {
if (v !== 'success')
return
onSuccess()
})
Use the pollingInterval
option to perform polling requests:
useAsyncData(() => $fetch('ok'), {
pollingInterval: 2000 // 2 seconds
})
// request to => 'ok'
// wait 2 seconds...
// request to => 'ok'
const { execute } = useAsyncData(() => $fetch('ok'), {
pollingInterval: 2000, // 2 seconds
immediate: false
})
// ...
// Will not poll until `execute` is called for the first time.
await execute() // request to => 'ok'
// wait 2 seconds...
// request to => 'ok'
Use the debounceInterval
option to apply debouncing:
const { execute } = useAsyncData(() => $fetch('ok'), {
debounceInterval: 2000 // 2 seconds
})
await execute()
// request to => 'ok'
execute()
execute()
// after about 2 seconds
// request to => 'ok'
Use the throttleInterval
option to apply throttling:
const { execute } = useAsyncData(() => $fetch('ok'), {
throttleInterval: 2000 // 2 seconds
})
await execute()
// request to => 'ok'
execute()
execute()
// after about 2 seconds
await execute()
// request to => 'ok'
You could customize useAsyncData
to configure your favorite default options:
import { useAsyncData as $ } from 'vfetcher'
export const useAsyncData = $.create({
immediate: false
})
const { execute } = useAsyncData(() => $fetch('ok'))
// ...
await execute()
The new useAsyncData
will extend the default options of the previous one:
import { useAsyncData as $1 } from 'vfetcher'
const $2 = $1.create({
debounceInternal: 150
})
const useAsyncData = $2.create({
immediate: false
})
useAsyncData(() => $fetch('ok'))
// Equal to:
// `useAsyncData(() => $fetch('ok'), { debounceInternal: 150, immediate: false })`
Except for execute/refresh
, all other variables are wrapped by ref:
data
: The result returned by the asynchronous request, defaulting tonull
, with the result being the return value ofofetch
.pending
: A boolean value indicating whether the data is still being fetched.error
: The error object if the data fetch fails, otherwisenull
.status
: A string representing the state of the data request (idle
,pending
,success
,error
).execute/refresh
: A function used to manually trigger the request.
immediate
: A boolean value indicating whether to make a request during initialization. Defaults to true.watch
: Watches a set of reactive sources, similar to the first parameter type of the Vuewatch
method. When the reactive sources change, a new request will be made. By default, it watches the request URL and request parameters (detailed below), but you can manually set it to false to disable this feature.pollingInterval
: Can be a reactive value. Pass anumber
, in milliseconds, to indicate the interval time for polling. By default, polling is not enabled.debounceInterval
: Can be a reactive value. Pass anumber
, in milliseconds, to indicate the debounce delay time. By default, debounce is not enabled.throttleInterval
: Can be a reactive value. Pass anumber
, in milliseconds, to indicate the throttle wait time. By default, throttling is not enabled.
useFetch
is almost a combination of useAsyncData
and ofetch
:
- The first parameter is basically the same as the first parameter of
ofetch
. - The second parameter accepts all configuration options of both
useAsyncData
andofetch
. - The return value is the same as that of
useAsyncData
.
Thanks to ofetch
, the data will be automatically converted to the appropriate type:
const { data: d1 } = useFetch('/return-ok')
watchEffect(() => {
console.log(d1.value)
// -> null
// -> 'ok'
})
const { data: d2 } = useFetch('/return-json')
watchEffect(() => {
console.log(d2.value)
// -> null
// -> { one: 1 }
})
Request parameters such as the request path, headers, query, body, etc., can be passed in as reactive values, which will automatically trigger requests when they change:
const url = ref('return-ok')
const query = ref({ one: '1' })
const { data } = useFetch(url, { query })
watchEffect(() => {
console.log(data.value)
})
// -> null
// -> 'ok'
url.value = 'return-query'
// -> { one: '1' }
query.value = { two: '2' }
// -> { two: '2' }
Similar to useAsyncData
, you can configure your preferred default parameters, as mentioned above:
import { useFetch as $ } from 'vfetcher'
export const useFetch = $.create({
// ...
})
useFetch
shares the same return values and options as useAsyncData
. It also accepts all options from ofetch
, and by default, it monitors the following parameters from ofetch
:
URL
: The request path URL.method
: The request method type.query
: Query parameters.params
: Just an alias forquery
.body
: The request body.headers
: Request headers.baseURL
: The base URL for the request.
... For other general options of
ofetch
, please refer to the ofetch official documentation.
Use usePagination
function to handle pagination.
import { usePagination } from 'vfetcher'
usePagination
is a wrapper around useFetch
:
- The first parameter is the same as in
usePagination
. - The second parameter is a configuration object, containing all the configurations of
useFetch
. - The return value includes all the return values of
useFetch
.
You can directly use the configuration options of useFetch
.
usePagination('ok', {
immediate: false
})
It automatically merge the params of pagination to query:
usePagination('getByPage')
// request to => `/getByPage?current=1&pageSize=10`
Compared to useFetch
, some new return values have been added, which are also responsive:
const { pageCurrent } = usePagination('getByPage')
// request to => `/getByPage?current=1&pageSize=10`
pageCurrent.value = 2
// request to => `/getByPage?current=2&pageSize=10`
Get pageSize and total data counts by lodash - get
, or you can configure the param key manually:
const { data, total } = usePagination('getByPage', {
totalKey: 'res.total'
})
watchEffect(() => {
console.log(data.value)
if (data.value)
console.log(total.value)
})
// -> null
// -> { res: { total:10, data:[ /* ... */]} }
// -> 10
Same as useFetch, you can also configure the default params you like. See above for details:
import { usePagination as $ } from 'vfetcher'
export const usePagination = $.create({
// ...
})
usePagination
includes all the options and return values of useFetch
. In addition, it also has some options and return values specific to itself.
All new return values are reactive variables:
pageCurrent
: Indicates the current page number (number).pageSize
: Indicates the number of items per page (number).total
: Indicates the total number of items (read-only number).pageTotal
: Indicates the total number of pages (read-only number).
New Options
pageCurrentKey
: Indicates the key name for the current page number, used in the query. Default is'current'
.pageSizeKey
: Indicates the key name for the number of items per page, used in the query. Default is'pageSize'
.defaultPageSize
: Indicates the default number of items per page (number), useful whenimmediate: true
. Default is10
.totalKey
: The key name for fetching the total number of items, obtained from the returned data usinglodash - get
. Default is'total'
.pageTotalKey
: The key name for fetching the total number of pages, obtained from the returned data usinglodash - get
. Default is'totalPage'
.