Best Request Solution in Vue.js Ecosystem
So far, the best request solution for the Vue.js ecosystem (excluding Nuxt) I currently recommend Axios + Pinia Colada.
Background
Vue.js is one of the most popular front-end application development frameworks in the world. Countless front-end applications are built on it. In most CSR (client-side rendering) front-end applications, how to organize the code to interact with the back-end is an eternal technical point.
Basic request library
Axios
Axios is a network request library based on promise, which can be used in browsers and Node.js (it uses the native Node.js http module on the server side, and XMLHttpRequest on the client side (browser side)). It is simple to use, small in size and provides an easy-to-extend interface. Axios is almost the most popular front-end request library at present.
ofetch
ofetch is an enhanced version of the fetch API and is the underlying request dependency of the Nuxt framework.
Traditional request encapsulation ideas
Currently, the most common request modules in Vue.js app are encapsulated based on Axios :
import axios from 'axios'
export const request = axios.create({
// Environment variable is often used to distinguish between local agents and online API
baseURL: 'xxx',
// Set Authorization, etc.
headers: {},
timeout: 10000,
})
// Request Interceptor
request.interceptors.request.use((config) => {
return config
}, (error) => {
return Promise.reject(error)
})
// Response Interceptor
request.interceptors.response.use((response) => {
return response.data
}, (error) => {
return Promise.reject(error)
})2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { request } from '@/utils/request'
export function getBusinessByIdApi(id) {
if (!id) {
return
}
return request.get(`/business?id=${id}`)
}2
3
4
5
6
7
8
9
<script lang="ts" setup>
import { getBusinessByIdApi } from '@/apis/business'
import { ref, shallowRef, watch } from 'vue'
import { useRoute } from 'vue-router'
const detail = shallowRef()
const loading = ref(false)
function refreshDetail(id) {
if (loading.value) {
return
}
loading.value = true
getBusinessByIdApi(id).then((data) => {
detail.value = data
}).catch((e) => {
console.error(e)
}).finally(() => {
loading.value = false
})
}
const route = useRoute()
watch(() => route.query.id, (id) => {
refreshDetail(id)
}, {
immediate: true
})
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Obviously, if you follow a certain paradigm to call the API, the whole process is still relatively cumbersome. From Axios encapsulation to data acquisition, you need to pass through three module nodes in sequence, and the code for obtaining data in the Vue component is always repeated code (sample code). Each request needs to be written from scratch, which leaves room for optimization.
Pinia Colada
Core API
Pinia Colada provides a set of optimal asynchronous state management solutions for the current Vue.js ecosystem based on Pinia. It uses the logic reuse solution composables provided by Vue.js to avoid writing a lot of boilerplate code to obtain data, and transparently supports practical functions such as caching and request deduplication.
useQuery
useQuery is the basic query usage provided by Pinia Colada, which is mainly used in scenarios where data is obtained:
<script lang="ts" setup>
import { getBusinessByIdApi } from '@/apis/business'
import { useQuery } from '@pinia/colada'
import { ref, shallowRef, watch } from 'vue'
import { useRoute } from 'vue-router'
const detail = shallowRef()
const loading = ref(false)
function refreshDetail(id) {
if (loading.value) {
return
}
loading.value = true
getBusinessByIdApi(id).then((data) => {
detail.value = data
}).catch((e) => {
console.error(e)
}).finally(() => {
loading.value = false
})
}
const route = useRoute()
const { data, isLoading, refresh } = useQuery({
key: () => ['getBusinessByIdApi', route.query.id],
query: () => getBusinessByIdApi(route.query.id)
})
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
useMutation
useMutation is mainly used to trigger and track the status of a step operation with side effects, mainly used in scenarios where data is written:
<script lang="ts" setup>
import { createBusinessApi } from '@/apis/business'
import { useMutation } from '@pinia/colada'
const {
mutate,
isLoading
} = useMutation({
mutation: data => createBusinessApi(data)
})
</script>2
3
4
5
6
7
8
9
10
11
import { request } from '@/utils/request'
export function createBusinessApi(data) {
if (!id) {
return
}
return request.post(`/business`, data)
}2
3
4
5
6
7
8
9
Core Features
- The data obtained by useQuery will be cached using Pinia, and the cached value will be used first when it is called again
- Requests initiated at the same time by useQuery will be de-duplicated when the key value is the same
Summarize
Pinia Colada is a rising star in the context of Vue.js 3.x. It embraces the Composition API and provides a more organized and modular code structure. It greatly reduces the boilerplate code for business requests while incorporating practical features such as caching and request deduplication. I personally think that in the context of fully embracing Vue.js 3.x, it is a more reasonable form of code organization than traditional writing.
