Vue3+Vite+TypeScript+Element Plus开发-07.Mockjs引用与Axios封装

news2025/4/15 10:26:34

系列文档目录

Vue3+Vite+TypeScript安装

Element Plus安装与配置

主页设计与router配置

静态菜单设计

Pinia引入

Header响应式菜单缩展

Mockjs引用与Axios封装

登录设计

登录成功跳转主页

多用户动态加载菜单

Pinia持久化

动态路由-配置 


文章目录

目录

系列文档目录

文章目录

前言

一、Mockjs

二、axios

三、Aside调整

参考文献:


前言

Mock.js 是一个用于模拟数据的 JavaScript 库。它可以帮助开发者快速生成模拟数据,用于前端开发中的接口测试、页面展示等场景,从而避免因后端接口未完成而导致前端开发进度受阻。

Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。它提供了简单易用的 API,用于发送各种类型的 HTTP 请求,如 GET、POST、PUT、DELETE 等。


一、Mockjs

1.安装

npm install mockjs

2.mock模拟数据构建

2.1在src文件夹下新建文件夹mock

2.2在mock文件夹下新建文件夹mockData

2.3在mockData文件夹下新建文件menu.ts

完整代码:

// src/mock/mockData/menu.ts
import Mock from 'mockjs';
import { Document, Setting } from '@element-plus/icons-vue'; // 假设你使用的是 Element Plus 的图标

// 模拟菜单数据
const menuData = Mock.mock({
  data: [
    { index: 'Home', label: '首页', icon: Document },
    {
      index: 'SysSettings',
      label: '系统设置',
      icon: Setting,
      children: [
        { index: 'UserInfo', label: '个人资料' },
        { index: 'AccountSetting', label: '账户设置' },
      ],
    },
  ],
});

export default menuData;

2.4.在mock文件夹下新建文件index.ts

// src/mock/index.ts
import Mock from 'mockjs';
import menuData from '@/mock/mockData/menuData';

Mock.mock(/menu/, 'get', (req: any) => {
  return menuData.data;
});

3.Mock引用

3.1修改main.ts文件

重点部分:

// 引入 Mock 数据
import './mock'

完整代码:

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import router from './router';
import App from './App.vue'
import { createPinia } from 'pinia'
// 引入 Mock 数据
import './mock'

// 创建 Pinia 实例
const pinia = createPinia();

const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
  }

app.use(ElementPlus, {
    locale: zhCn,
  })
  app.use(router);
  app.use(pinia);

app.mount('#app')

二、axios

1.安装

npm install axios

2.axios封装

2.1在src文件夹下新建文件夹api

2.2在api下新建文件request.ts

在baseURL: 'http://127.0.0.1:5173' 根据实际情况填写,具体参考运行时候网址,待api数据可以的时候调整baseURL指向可以无缝隙切换(后续会增加正式区与测试区自行切换)

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';

// 创建 axios 实例
const instance: AxiosInstance = axios.create({
  baseURL: 'http://127.0.0.1:5173', // 'http://127.0.0.1:8080', // 替换为你的 API 基础地址
  timeout: 5000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json'
  }
});

// 请求拦截器
instance.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // 在发送请求之前做些什么,例如添加 Token
    const token = localStorage.getItem('token'); // 假设使用 localStorage 存储 token
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    // 增加 API KEY
    const api_key = 'Test';
    if (api_key) {
      config.headers['api_key'] = `${api_key}`;
    }
    return config;
  },
  (error: AxiosError) => {
    // 对请求错误做些什么
    console.error('请求错误:', error);
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    // 对响应数据做点什么
    return response.data; // 直接返回数据
  },
  (error: AxiosError) => {
    // 对响应错误做点什么
    if (error.response) {
      // 请求已发出,但服务器响应的状态码不在 2xx 范围内
      console.error('响应错误:', error.response);
      return Promise.reject(error.response.data); // 返回后端返回的错误数据
    } else if (error.request) {
      // 请求已发出,但没有收到响应
      console.error('请求错误:', error.request);
      return Promise.reject(error.request);
    } else {
      // 在设置请求时触发了错误
      console.error('请求设置错误:', error.message);
      return Promise.reject(error.message);
    }
  }
);

// 封装常用的请求方法
export const request = (url: string, data: any = {}, method: string = 'GET') => {
  return instance({
    url,
    method,
    data: method.toUpperCase() === 'GET' ? null : data,
    params: method.toUpperCase() === 'GET' ? data : null
  });
};

// 封装 POST 请求
export const post = (url: string, data: any = {}) => {
  return request(url, data, 'POST');
};

// 封装 GET 请求
export const get = (url: string, params: any = {}) => {
  return request(url, params, 'GET');
};

在该项目中,表头新增api_key,可以根据实际情况进行删除或保留

    // 增加 API KEY
    const api_key = 'Test';
    if (api_key) {
      config.headers['api_key'] = `${api_key}`;
    }

 2.3在api文件夹下新建menu.ts

// 引入 request、post 和 get 函数 
import { get } from '@/api/request'; // 绝对路径

// 登录接口
export const menuAPI = async () => {
  try {
    const result = await get('/menu'); // 使用封装的 get 方法
    return result  ;
  } catch (error) {
    console.error('获取菜单数据失败:', error);
    return [];
  }
};

三、Aside调整

1.调整MainAsideCont.vue

menu数据原是引用固定,现改为引用api资料

/*
const menuData = ref<MenuItem[]>([
  { index: 'Home', label: '首页', icon: Document },
  {
    index: 'SysSettings',
    label: '系统设置',
    icon: Setting,
    children: [
      { index: 'UserInfo', label: '个人资料' },
      { index: 'AccountSetting', label: '账户设置' },
    ],
  },
]);
*/
// 确保 menuAPI 是一个数组,并赋值给 menuData
const menuData = ref<MenuItem[]>([]); // 初始化为空数组

// 封装数据获取和处理逻辑
const fetchMenuData = async () => {
  try {
    const result = await menuAPI(); // 调用异步 API 获取数据
    console.error('menuAPI :', result);
    if (Array.isArray(result)) {
      menuData.value = result as MenuItem[]; // 确保结果是 MenuItem[] 类型
    } else {
      console.error('menuAPI 返回的数据不是数组:', result);
    }
  } catch (error) {
    console.error('获取菜单数据失败:', error);
  }
};

 完整代码:

<template> 
  <el-menu
    :default-active="activeIndex"
    class="el-menu-vertical-demo"
    :collapse="isCollapse"
  >
  <h3 :key="TitleText">{{TitleText}}</h3>
    <!-- 渲染没有子菜单的项 -->
    <el-menu-item
      v-for="item in noChilden"
      :key="item.index"
      :index="item.index"
      @click="handlemenu(item)"
    >
      <component class="icon" :is="item.icon"></component>
      <span>{{ item.label }}</span>
    </el-menu-item>

    <!-- 渲染有子菜单的项 -->
    <el-sub-menu
      v-for="item in hasChilden"
      :key="item.index"
      :index="item.index"
    >
      <template #title>
        <component class="icon" :is="item.icon"></component>
        <span>{{ item.label }}</span>
      </template>
      <el-menu-item
        v-for="subItem in item.children"
        :key="subItem.index"
        :index="subItem.index"
        @click="handlemenuchild(item, subItem)"
      >
        <span>{{ subItem.label }}</span>
      </el-menu-item>
    </el-sub-menu>
  </el-menu>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import { defineComponent } from 'vue';
import { useRouter } from 'vue-router';
import {
  Document,
  Setting,
} from '@element-plus/icons-vue';

import { useAllDataStore } from '@/stores';

import { menuAPI } from '@/api/menu'; 

interface MenuItem {
  index: string;
  label: string;
  icon?: any;
  children?: MenuItem[];
}
/*
const menuData = ref<MenuItem[]>([
  { index: 'Home', label: '首页', icon: Document },
  {
    index: 'SysSettings',
    label: '系统设置',
    icon: Setting,
    children: [
      { index: 'UserInfo', label: '个人资料' },
      { index: 'AccountSetting', label: '账户设置' },
    ],
  },
]);
*/
// 确保 menuAPI 是一个数组,并赋值给 menuData
const menuData = ref<MenuItem[]>([]); // 初始化为空数组

// 封装数据获取和处理逻辑
const fetchMenuData = async () => {
  try {
    const result = await menuAPI(); // 调用异步 API 获取数据
    console.error('menuAPI :', result);
    if (Array.isArray(result)) {
      menuData.value = result as MenuItem[]; // 确保结果是 MenuItem[] 类型
    } else {
      console.error('menuAPI 返回的数据不是数组:', result);
    }
  } catch (error) {
    console.error('获取菜单数据失败:', error);
  }
};

onMounted(() => {
  fetchMenuData(); // 在组件挂载时调用 fetchMenuData 函数
});



const hasChilden = computed(() => menuData.value.filter(item => item.children && item.children.length > 0));
const noChilden = computed(() => menuData.value.filter(item => !item.children || item.children.length === 0));

const activeIndex = ref('Home');
const router = useRouter();

const handlemenu = (item: MenuItem) => {
  router.push(item.index);
};

const handlemenuchild = (item: MenuItem, subItem: MenuItem) => {  
  router.push(subItem.index);
};

 
// const isCollapse = ref(true)
const store = useAllDataStore();
const TitleText = computed(() => {
  return store.isCollapse ? '平台' : '测试平台管理';
});

const isCollapse = computed(() => store.isCollapse); 
/*
// 使用 defineComponent 显式命名组件
export const MainAsideCont = defineComponent({
  name: 'MainAsideCont'
});
*/

</script>

<style>
.el-menu {
  height: 100%; /* 设置整个布局的高度为 100%,确保布局占满整个视口 */
  border-right: none; /* 去掉右边框 */
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 180px;
   min-height: 400px;
}
.el-menu-vertical-demo.el-menu--collapse {
  width: 60px; /* 收缩时的宽度 */
}

.icon {
  margin-right: 8px; /* 图标与文字之间的间距 */
  font-size: 18px;   /* 图标的大小 */
  width:18px;
  height:18px;
  size:8px;
  color: #606266;    /* 图标的默认颜色 */
  vertical-align: middle; /* 垂直居中对齐 */
}

/* 鼠标悬停时的样式 */
.icon:hover {
  color: #409eff; /* 鼠标悬停时图标的颜色 */
}

</style>

四 、运行效果

点击expand

菜单数据来源Mock模拟资料,也就是api资料。


参考文献:

  1. Axios 官方网址https://axios-http.com/
  2. Mockjs官方网址https://mockjs.com/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】背景知识

一、Redis的特性 Redis是一种基于键值对&#xff08;key-value&#xff09;的NoSQL数据库&#xff0c;与很多键值对数据库不同的是&#xff0c;Redis中的值可以是由string&#xff08;字符串&#xff09;&#xff0c;hash&#xff08;哈希&#xff09;&#xff0c;list&#xf…

航电系统的任务载荷集成技术要点概述!

一、任务载荷集成技术难点 1. 接口标准化与兼容性 异构设备协议冲突&#xff1a;不同厂商的载荷设备&#xff08;如光学相机、雷达、电子战模块&#xff09;采用不同的通信协议&#xff08;如1553B、RS422、以太网&#xff09;&#xff0c;需设计统一的总线接口标准以支持即…

OceanBase V4.3.5 上线全文索引功能,让数据检索更高效

近日&#xff0c;OceanBase 4.3.5 BP1 版本正式推出了企业级全文索引功能。该版本在中文分词、查询效率及混合检索能力上进行了全面提升。经过自然语言模式和布尔模式在不同场景下的对比测试&#xff0c;OceanBase 的全文索引性能明显优于 MySQL。 点击下载 OceanBase 社区版…

Qt中的信号与槽及其自定义

信号源&#xff1a;哪个控件发的信号 信号的类型&#xff1a;用户进行不同的操作就会触发不同的信号 如点击按钮&#xff0c;在输入框移动光标&#xff0c;勾选一个复选框&#xff0c;选 择一个下拉框 信号的处理方式&#xff1a;槽(slot)----也就是函数&#xff0c;Qt中用con…

【PFPGA学习】状态机思想编程HDLbitsFPGA练习

目录 一、用状态机实现LED流水灯 1.1状态机思想 1.2状态机思想LED流水灯 1.3 modesim仿真 1.4 FPGA烧录实现 二、CPLD和FPGA芯片 1. 核心结构与技术原理 2. 性能与容量 3. 适用场景 &#xff14;. 选型建议 三、HDLbitsFPGA练习记录&#xff08;combinational logic…

Android 中集成 Unity 工程的步骤

在 Adroid 项目中集成 Unity 工程,主要步骤如下: 一、前提条件 1、已有一个 Android 工程项目; 2、Unity 工程已导出为 Android 工程,目录大概如下: 二、集成步骤 1、在 Android 工程中导入 Unity 工程的 unityLibrary 模块。 在 Android Studio 中,点击菜单栏 Fil…

Python从入门到精通全套视频教程免费

概述 &#x1f4e2; 所有想学Python的小伙伴看过来&#xff01;作为深耕编程领域的技术分享者&#xff0c;最新整理了一份Python从0到1的视频教程。 &#x1f4a1;亮点 ✅ 保姆级系统路线&#xff1a;从环境搭建、语法精讲&#xff0c;到爬虫/数据分析/AI/Web全栈开发&#…

蓝桥杯:对字符串处理常用知识笔记

一、前面四个是计算带有空格字符串的的长度计算 C语言代码 #include<string.h> #include<stdio.h> int main() { char s[105]; gets(s); printf("%d", strlen(s)); return 0; } 算法2 C 代码&#xff08;常用&#xff09; #include <iostream> #in…

实现一个 Markdown 编辑器组件:Vue 3 + Vite + Highlight.js

文章目录 一、项目背景与需求分析二、搭建基础项目1. 初始化 Vue 3 项目2. 安装依赖 三、实现 Markdown 编辑器组件1. 创建 Markdown 编辑器组件2. 组件说明 四、优化与拓展1. 自动保存功能2. 文件上传功能 五、总结 一、项目背景与需求分析 在现代前端开发中&#xff0c;Mark…

帆软fvs文件中某表格新增数据来声提醒

1.上传音频文件到帆软安装目录的指定环境 准备一个音频文件&#xff08;如 mp3 格式&#xff09;&#xff0c;并将其放置在合适的目录。 例如&#xff1a;%FR_HOME%\webapps\webroot\help 2.点击 FVS 模板左上角「模板>页面加载结束事件」&#xff0c;输入以下 JavaScript …

从零用java实现 小红书 springboot vue uniapp (11)集成AI聊天机器人

前言 移动端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 项目整体介绍及演示 前面的文章我们主要完成了基础模块的开发 这次我们跟一下热点 创建AI聊天机器人 并嵌入到我们的uniapp中 首先需要了解dify我已经完成了搭建win10 VMware安装ubuntu…

$_POST 超级全局变量

$_POST 是一个超级全局变量&#xff0c;在 PHP 中用于收集通过 HTTP POST 方法发送到服务器的数据。与 $_GET 不同&#xff0c;$_POST 允许发送大量数据&#xff0c;且数据不会显示在 URL 中&#xff0c;因此更适用于提交敏感信息&#xff0c;如用户登录信息、表单数据等。 使…

开发一个环保回收小程序需要哪些功能?环保回收小程序

废品分类展示与识别 详细分类列表&#xff1a;清晰展示常见废品类型&#xff0c;如废纸&#xff08;报纸、书本纸、包装纸等&#xff09;、塑料&#xff08;塑料瓶、塑料容器、塑料薄膜等&#xff09;、金属&#xff08;易拉罐、铁制品、铜制品等&#xff09;、玻璃&#xff0…

Debezium嵌入式连接postgresql封装服务

文章目录 1.项目结构&#xff1a;2.依赖&#xff1a;3.application.properties4.DebeziumConnectorConfig类5.TableEnum类6.TableHandler接口&#xff08;表处理抽象&#xff09;7.DefaultTableHandler默认实现类8.UserTableHandler处理类9.TableHandlerFactory工厂10.Debezium…

Python 爬取 1688.item_get_factory 接口:获取工厂档案信息实战指南

在电商采购和供应链管理中&#xff0c;了解供应商的工厂信息是至关重要的一步。1688 作为国内领先的 B2B 平台&#xff0c;提供了丰富的供应商和工厂档案信息。通过 item_get_factory API 接口&#xff0c;开发者可以获取工厂的详细信息&#xff0c;包括工厂名称、地址、联系方…

Rust所有权详解

文章目录 Rust所有权所有权规则作用域 内存和分配移动与克隆栈空间堆空间 关于函数的所有权机制作为参数作为返回值 引用与租借垂悬引用 Rust所有权 C/C中我们对于堆内存通常需要自己手动管理&#xff0c;手动申请和释放&#xff0c;即便有了智能指针&#xff0c;对于效率的影…

CExercise_07_1指针和数组_2数组元素的逆序数组逆序(指针版 reverse_by_ptr 和下标版 reverse_arr)

题目&#xff1a; 数组元素的逆序。要求使用[]运算符以及纯粹指针操作两种方式来完成。 关键点 arr[i] arr[len - 1 - i]; arr[0]arr[len-1]; 如果数组序列是偶数,则调换最中间一对为止;若为奇数,则单出一个不用反转. 思想就是长度取一半 eg:8/2, 9/24.5,反转一半,到5时固定…

框架PasteForm实际开发案例,换个口味显示数据,支持echarts,只需要标记几个特性即可在管理端显示(2)

PasteForm框架的主要思想就是对Dto进行标记特性,然后管理端的页面就会以不一样的UI呈现 使用PasteForm框架开发,让你免去开发管理端的烦恼,你只需要专注于业务端和用户端! 在管理端中,如果说表格是基本的显示方式,那么图表chart就是一个锦上添花的体现! 如果一个项目拥…

Starrocks的Bitmap索引和Bloom filter索引以及全局字典

写这个的主要作用是梳理一下Starrocks的索引效率以及使用场景。 Starrocks Bitmap索引 原理&#xff1a; Bitmap 索引是一种使用 bitmap 的特殊数据库索引。bitmap 即为一个 bit 数组&#xff0c;一个 bit 的取值有两种&#xff1a;0 或 1。 每一个 bit 对应数据表中的一行&…

QML面试笔记--UI设计篇05容器控件

1. QML中容器控件全解&#xff1a;构建灵活界面的基石 1.1. Item&#xff08;万物容器&#xff09;1.2. Rectangle&#xff08;视觉容器&#xff09;1.3. ListView&#xff08;动态列表容器&#xff09;1.4. Frame&#xff08;表单容器&#xff09;1.5. SwipeView&#xff08;页…