vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3拦截器作用和写法

一文详解Vue3项目中的拦截器的作用和写法

作者:南雨北斗

在 Vue 3 项目中,拦截器(Interceptors)主要指 Axios 拦截器,它充当了前端应用与后端服务器之间的一个中间件层,其核心作用是在请求发送前或响应接收后,对数据进行统一拦截和处理,下面给大家具体说说,需要的朋友可以参考下

在 Vue 3 项目中,拦截器(Interceptors)主要指 Axios 拦截器,它充当了前端应用与后端服务器之间的一个中间件层。其核心作用是在请求发送前或响应接收后,对数据进行统一拦截和处理。

具体来说,Vue 3 项目中的拦截器主要有以下四大核心作用:

1. 请求拦截器(Request Interceptor)

在请求发送到服务器之前进行统一处理,避免在每个业务接口中重复编写相同的逻辑:

2. 响应拦截器(Response Interceptor)

在接收到服务器响应之后、业务代码处理数据之前进行统一处理:

3. 全局错误处理

拦截器可以捕获网络请求中出现的各类异常,并进行统一的兜底处理,大幅提升用户体验和代码的健壮性:

4. 提升代码质量与可维护性

补充说明:除了 Axios 拦截器,Vue 3 项目中还有 Vue Router 导航守卫(Navigation Guards)。它主要用于拦截页面的路由跳转,常用于页面级别的权限验证(如未登录禁止访问后台页面)、页面标题设置或数据预加载等。两者结合使用,可以构建非常完善的前端安全与交互体系。

下面是一个拦截器的例子:

1. Axios 请求/响应拦截器(核心)

通常在 src/utils/request.js 中封装,配合 ref 管理全局 Loading。

// src/utils/request.js
import axios from 'axios';
import { useUserStore } from '@/stores/user'; // Pinia 用户状态
import { ElMessage } from 'element-plus'; // UI 框架提示
// 1. 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_BASE_API, // 环境变量
  timeout: 10000,
});
// 2. 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 开启 Loading(配合 Element Plus 的 v-loading 指令全局控制)
    // 这里可以添加一个全局 loading 计数器
    // 自动添加 Token
    const userStore = useUserStore();
    if (userStore.token) {
      config.headers.Authorization = `Bearer ${userStore.token}`;
    }
    // 处理特殊请求头(如 FormData)
    if (config.data instanceof FormData) {
      config.headers['Content-Type'] = 'multipart/form-data';
    }
    return config;
  },
  (error) => {
    // 请求配置出错(如 URL 格式错误)
    return Promise.reject(error);
  }
);
// 3. 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 关闭 Loading
    // 后端约定 code===200 为成功
    const { code, message, data } = response.data;
    if (code === 200) {
      return data; // 直接返回业务数据,简化调用
    } else {
      // 业务错误统一处理
      ElMessage.error(message || '请求失败');
      return Promise.reject(new Error(message));
    }
  },
  (error) => {
    // 网络超时、服务器 500 等错误
    if (error.response) {
      const { status } = error.response;
      if (status === 401) {
        // Token 失效:清除状态并跳转登录
        const userStore = useUserStore();
        userStore.logout();
        window.location.href = '/login';
      } else if (status === 403) {
        ElMessage.error('没有权限访问');
      } else {
        ElMessage.error(error.response.data?.message || '系统错误');
      }
    } else if (error.message.includes('timeout')) {
      ElMessage.error('请求超时,请稍后重试');
    } else {
      ElMessage.error('网络异常,请检查连接');
    }
    return Promise.reject(error);
  }
);
export default service;

2. 组件级渲染错误拦截(onErrorCaptured)

在父组件中捕获子组件异常,防止白屏。

<template>
  <ChildComponent />
</template>
<script setup>
import { onErrorCaptured } from 'vue';
import { ElMessage } from 'element-plus';
// 捕获后代组件的错误
onErrorCaptured((err, instance, info) => {
  console.error('子组件错误:', err, info);
  ElMessage.error('页面渲染出现异常');
  // 返回 false 阻止错误继续向上传播
  return false;
});
</script>

3. 应用全局错误拦截(app.config.errorHandler)

在 main.js 中注册,捕获所有未被组件捕获的错误。

// main.js
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.config.errorHandler = (err, vm, info) => {
  console.error('全局捕获错误:', err, info);
  // 上报到 Sentry 或自己的日志平台
  // reportErrorToServer(err);
};
app.mount('#app');

4. 路由导航守卫(路由拦截)

在 src/router/index.js 中配置,用于权限控制。

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import { useUserStore } from '@/stores/user';
const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/login', component: () => import('@/views/Login.vue') },
    { path: '/dashboard', component: () => import('@/views/Dashboard.vue'), meta: { requiresAuth: true } },
  ],
});
// 全局前置守卫
router.beforeEach((to, from, next) => {
  const userStore = useUserStore();
  const isLoggedIn = !!userStore.token;
  if (to.meta.requiresAuth) {
    if (isLoggedIn) {
      next(); // 已登录,放行
    } else {
      next({ path: '/login', query: { redirect: to.fullPath } }); // 未登录,跳转登录
    }
  } else {
    // 如果已登录且访问登录页,直接跳转首页
    if (to.path === '/login' && isLoggedIn) {
      next({ path: '/' });
    } else {
      next();
    }
  }
});
export default router;

5. 在组件中使用封装好的请求

<script setup>
import request from '@/utils/request';
const fetchData = async () => {
  try {
    // 直接拿到 data,无需再解构
    const res = await request.get('/user/info');
    console.log(res);
  } catch (error) {
    // 拦截器已经提示了错误,这里只需处理特殊逻辑
    console.log('请求失败');
  }
};
</script>

关键点总结

拦截器类型核心作用常见写法位置
Axios 请求拦截加 Token、启动 Loadingrequest.js
Axios 响应拦截解构数据、统一错误提示、401跳转request.js
组件错误拦截捕获子组件渲染异常父组件 onErrorCaptured
全局错误拦截兜底所有未捕获错误main.js
路由拦截登录鉴权、页面权限控制router/index.js

到此这篇关于一文详解Vue3项目中的拦截器的作用和写法的文章就介绍到这了,更多相关Vue3拦截器作用和写法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文