UNPKG

vfetcher

Version:

Vue composables for fetching data, based on unjs/ofetch

386 lines (282 loc) 11.2 kB
# vfetcher English | [简体中文](/README-zh.md) Vue composables for fetching data, based on [unjs/ofetch](https://github.com/unjs/ofetch). ```sh $ pnpm i vfetcher ``` ## Features - Carefully designed API: Intentionally mimicking the [nuxt/useFetch](https://nuxt.com.cn/docs/api/composables/use-fetch) 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! ## Usage > Visit [examples](/examples/src/) to see the config examples, visit [test](/test/) to see the usage examples. ### Re-export ofetch `vfetcher` re-export all exports of `ofetch` so you can directly use ofetch: ```ts import { $fetch } from 'vfetcher/ofetch' ``` ### Basic Examples 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: ```ts 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: ```ts 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: ```ts 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: ```ts 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: ```ts const { status } = useAsyncData(() => $fetch('ok')) // Equivalent to `onSuccess` hook: watch(status, (v) => { if (v !== 'success') return onSuccess() }) ``` 通过 `transform` 选项对返回值进行预处理: ```ts const { data } = useAsyncData(() => $fetch('post', { method: 'post', body: { number: { one: 1 } } }), { transform: (res: { number: { one: 1 } }) => res.number.one }) // request to => 'post' // response `{ number: { one: 1 } }` data.value === 1 // true ``` Use the `pollingInterval` option to perform polling requests: ```ts 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: ```ts 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: ```ts 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' ``` ### Customize the default options You could customize `useAsyncData` to configure your favorite default options: ```ts 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: ```ts 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 })` ``` ### Returns Except for `execute/refresh`, all other variables are wrapped by ref: - `data`: The result returned by the asynchronous request, defaulting to `null`, with the result being the return value of `ofetch`. - `pending`: A boolean value indicating whether the data is still being fetched. - `error`: The error object if the data fetch fails, otherwise `null`. - `status`: A string representing the state of the data request (`idle`, `pending`, `success`, `error`). - `execute/refresh`: A **function** used to manually trigger the request. ### Options - `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 Vue `watch` 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. - `transform`: A function that can be used to alter handler function result after resolving. - `default`: A function which returns the initial value of `data` above. - `pollingInterval`: Can be a reactive value. Pass a `number`, in milliseconds, to indicate the interval time for polling. By default, polling is not enabled. - `debounceInterval`: Can be a reactive value. Pass a `number`, in milliseconds, to indicate the debounce delay time. By default, debounce is not enabled. - `throttleInterval`: Can be a reactive value. Pass a `number`, in milliseconds, to indicate the throttle wait time. By default, throttling is not enabled. ## useFetch `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` and `ofetch`. - The return value is the same as that of `useAsyncData`. Thanks to `ofetch`, the data will be automatically converted to the appropriate type: ```ts 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: ```ts 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: ```js 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 for `query`. - `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](https://github.com/unjs/ofetch). ## Pagination Use `usePagination` function to handle pagination. `import { usePagination } from 'vfetcher'` ### Basic usage `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`. ```ts usePagination('ok', { immediate: false }) ``` It automatically merge the params of pagination to query: ```ts usePagination('getByPage') // request to => `/getByPage?current=1&pageSize=10` ``` Compared to `useFetch`, some new return values have been added, which are also responsive: ```ts 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: ```ts 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: ```js import { usePagination as $ } from 'vfetcher' export const usePagination = $.create({ // ... }) ``` ### New Return Values and Options `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 when `immediate: true`. Default is `10`. - `totalKey`: The key name for fetching the total number of items, obtained from the returned data using `lodash - get`. Default is `'total'`. - `pageTotalKey`: The key name for fetching the total number of pages, obtained from the returned data using `lodash - get`. Default is `'totalPage'`.