Vue3 provide全局注入API类 组件this.$api为undefined报错
问题原因
你遇到的this.$api为undefined的问题核心是两个API使用误区:
- Vue3的
provide/inject机制不会自动将注入值绑定到组件实例this上,必须在每个使用的组件内显式通过inject声明接收,才能访问注入内容,直接读this.$api自然是undefined。 - Vue3已经移除了Vue2中通过
Vue.prototype挂载全局属性的写法,直接照搬旧版本逻辑无法生效。
解决方案
两种实现方式选其一即可,第一种更贴合你Vue2的使用习惯,不需要修改现有组件的调用代码。
方案1:全局属性挂载(推荐)
这是Vue3官方提供的替代Vue.prototype的方案,挂载后所有组件可以直接通过this.$api访问实例,完全兼容你现有组件的调用写法。
只需要修改app.js的配置,把原来的.provide('$api', apis)替换为全局属性挂载即可,修改后代码如下:
import { createApp, h } from 'vue'; import { createInertiaApp } from '@inertiajs/inertia-vue3'; import api from './Models/_api' const apis = new api(); createInertiaApp({ resolve: (name) => require(`./Pages/${name}.vue`), setup({ el, app, props, plugin }) { const appInstance = createApp({ render: () => h(app, props) }) .use(plugin) .mixin({ methods: { route } }) // 全局挂载api实例,替代原provide写法 appInstance.config.globalProperties.$api = apis; return appInstance.mount(el); }, });
改完后组件里原有的this.$api.post()等调用逻辑不需要任何修改,可直接正常运行。
方案2:正确使用provide/inject注入
如果你坚持用provide做依赖注入,需要在每一个调用$api的组件里显式声明inject接收注入值,才能正常访问。
app.js里的provide写法不需要改动,只需要修改组件代码,添加inject声明:
<template> // 页面HTML内容 </template> <script> export default { // 必须显式声明接收注入的$api inject: ['$api'], data(){ return{ tableData:[], } }, methods:{ fetchData(){ this.$api.post('/api/user-data', {}).then(response=>{ if(response.status === 200) { this.tableData = response.data.data } }); } }, created(){ this.fetchData(); }, } </script>
如果后续用
<script setup>的组合式API写法,需要在setup内通过const $api = inject('$api')的方式接收,不能通过this访问。
额外代码优化建议
你目前写的api类存在冗余包装,axios本身就返回Promise,不需要额外套一层new Promise,还可以提前创建axios实例统一做全局配置,简化后的代码参考:
import axios from 'axios' // 统一创建axios实例,可配置baseURL、全局请求/响应拦截器、超时时间等 const request = axios.create({ timeout: 10000 }) export default class { get(url, params = {}) { return request.get(url, { params }).then(res => res.data) } post(url, payload = {}) { return request.post(url, payload).then(res => res.data) } find(url) { // find和get逻辑完全一致,直接复用get方法即可 return this.get(url) } }
axios默认会把所有非2xx状态的请求自动抛到catch分支,不需要你每次手动判断response.status === 200,能减少很多重复代码。
内容的提问来源于stack exchange,提问作者Rubal Gulati
相关产品推荐
相关产品推荐

