背景
在vue-axios
官方文档提供的说明方法中使用了any
类型,导致我们使用的时候无法推断类型,官方例子如下:
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App).use(store)
app.use(VueAxios, axios)
app.provide('axios', app.config.globalProperties.axios) // provide 'axios'
app.mount('#app')
// App.vue
import { inject } from 'vue'
export default {
name: 'Comp',
setup() {
const axios: any = inject('axios') // inject axios
const getList = (): void => {
axios
.get(api)
.then((response: { data: any }) => {
console.log(response.data)
});
};
return { getList }
}
}
在项目中的使用方式
改造以下官方例子,使之符合我们的项目规范。
首先,创建以下几个文件:
创建一个symbols.ts
文件存放我们的inject
类型的key
创建一个useAxios.ts
文件,作为hook
使用axios
,
其次,在main.ts
引入useAxios.ts
// symbols.ts
export const AxiosKey = Symbol('axios');
// useAxios.ts
import axios from 'axios';
import VueAxios from 'vue-axios';
import { App } from 'vue';
import { AxiosKey } from './symbols';
export function useAxios(app: App) {
axios.interceptors.response.use( // 添加响应拦截器
function (response) {
return response.data; // 只返回响应的数据,不返回其他配置信息
},
function (error) {
return Promise.reject(error); // 对响应错误做点什么
}
);
// 更多操作...
app.use(VueAxios, axios);
app.provide(AxiosKey, app.config.globalProperties.axios);
}
// main.ts
import { useAxios } from './useAxios';
const app = createApp(App);
useAxios(app); // 使用vue-axios
其次,通过以上步骤,接下来我们就可以在hook
中使用axios
了
// useTable.ts
import { inject, ref } from 'vue';
import { AxiosKey } from './symbols';
export default function useTable() {
const axios: any = inject(AxiosKey);
const fetchList = () => {
axios.get('urlxx', {
params: {
id: '123'
}
}).then((res) => {
console.log(res.data);
})
}
}
解决any问题
上面的hook
中axios
还是any
类型的,接下来我们改造一下,解决any
问。借助InjectionKey
方法把类型注入。
改造symbols.ts
为如下:
// symbols.ts
import { InjectionKey } from 'vue';
import { AxiosInstance } from 'axios';
export const AxiosKey: InjectionKey<AxiosInstance> = Symbol('axios');
修改hook
,去掉any
// useTable.ts
import { inject, ref } from 'vue';
import { AxiosKey } from './symbols';
export default function useTable() {
const axios = inject(AxiosKey);
const fetchList = () => {
axios.get('urlxx', {
params: {
id: '123'
}
}).then((res) => {
console.log(res.data);
})
}
}
但是还有问题,inject
的时候会出现undefined
提示,这时候需要对inject
方法进行封装一下,放在utils.ts
文件中
// util.ts
import { inject, InjectionKey } from 'vue';
/**
* 解决使用inject的时候undefined问题
* @param key
* @param fallback
* @returns
*/
export function injectStrict<T>(key: InjectionKey<T>, fallback?: T) {
const resolved = inject(key, fallback);
if (!resolved) {
throw new Error(`Could not resolve ${key.description}`);
}
return resolved;
}
此时,在hook
中使用injectStrict
替换inject
// useTable.ts
import { inject, ref } from 'vue';
import { AxiosKey } from './symbols';
import { injectStrict } from './utils';
export default function useTable() {
const axios = injectStrict(AxiosKey);
const fetchList = () => {
axios.get('urlxx', {
params: {
id: '123'
}
}).then((res) => {
console.log(res.data);
})
}
}
通过以上操作,any
问题彻底解决。
最终代码
// symbols.ts
import { InjectionKey } from 'vue';
import { AxiosInstance } from 'axios';
export const AxiosKey: InjectionKey<AxiosInstance> = Symbol('axios');
// util.ts
import { inject, InjectionKey } from 'vue';
/**
* 解决使用inject的时候undefined问题
* @param key
* @param fallback
* @returns
*/
export function injectStrict<T>(key: InjectionKey<T>, fallback?: T) {
const resolved = inject(key, fallback);
if (!resolved) {
throw new Error(`Could not resolve ${key.description}`);
}
return resolved;
}
// useAxios.ts
import axios from 'axios';
import VueAxios from 'vue-axios';
import { App } from 'vue';
import { AxiosKey } from './symbols';
export function useAxios(app: App) {
axios.interceptors.response.use( // 添加响应拦截器
function (response) {
return response.data; // 只返回响应的数据,不返回其他配置信息
},
function (error) {
return Promise.reject(error); // 对响应错误做点什么
}
);
// 更多操作...
app.use(VueAxios, axios);
app.provide(AxiosKey, app.config.globalProperties.axios);
}
// main.ts
import { useAxios } from './useAxios';
const app = createApp(App);
useAxios(app); // 使用vue-axios
// useTable.ts
import { inject, ref } from 'vue';
import { AxiosKey } from './symbols';
import { injectStrict } from './utils';
export default function useTable() {
const axios = injectStrict(AxiosKey);
const fetchList = () => {
axios.get('urlxx', {
params: {
id: '123'
}
}).then((res) => {
console.log(res.data);
})
}
}
相关文章
# Using axios globally in a Vue 3 with provide/inject (composition API)