第5天(二次封装axios)

98 阅读3分钟

一.两个小的优化

调整侧边栏收缩的流畅度,在el-menu下增加:

:collapse-transition="false"

el-card的阴影:

<el-card class="user-card" shadow="hover">

二.左下方表格的实现

设置tableData和tableLabel的数据:

const tableData = ref([
    {
      name: "A",
      todayBuy: 100,
      monthBuy: 200,
      totalBuy: 300,
    },
    {
      name: "B",
      todayBuy: 100,
      monthBuy: 200,
      totalBuy: 300,
    }
])

const tableLabel = ref({
    name: "产品",
    todayBuy: "今日购买",
    monthBuy: "本月购买",
    totalBuy: "总购买",
})

把数据渲染到表格中:(先新建一个el-crad)

<el-card class="user-table" shadow="hover">
        <el-table :data="tableData">
          <el-table-column v-for="(val,key) in tableLabel" 
          :key="key"
          :prop="key"
          :label="val">
          </el-table-column>
        </el-table>
      </el-card>

image.png

image.png 实现的效果:

image.png

三.axios请求数据

安装axios:

 npm install axios -D

mock.js:

import mock from 'mockjs'
import homeApi from './mockData/home'

mock.mock("/api/home/getTableData", 'get', homeApi.getTableData)

image.png

home.js中存的数据:

export default {
    getTableData: () => {
        return {
            code: 200,
            data: [
                {
                    name: "oppo",
                    todayBuy: 500,
                    monthBuy: 3500,
                    totalBuy: 22000,
                },
                {
                    name: "vivo",
                    todayBuy: 300,
                    monthBuy: 2200,
                    totalBuy: 24000,
                },
                {
                    name: "苹果",
                    todayBuy: 800,
                    monthBuy: 4500,
                    totalBuy: 65000,
                },
                {
                    name: "小米",
                    todayBuy: 1200,
                    monthBuy: 6500,
                    totalBuy: 45000,
                },
                {
                    name: "三星",
                    todayBuy: 300,
                    monthBuy: 2000,
                    totalBuy: 34000,
                },
                {
                    name: "魅族",
                    todayBuy: 350,
                    monthBuy: 3000,
                    totalBuy: 22000,
                },
            ],
        }
    }
}

main.js中引入:

import "../src/api/mock"

Home组件中进行axios请求:

// 使用 onMounted 钩子在组件挂载时进行数据请求
onMounted(async () => {
  try {
    const response = await axios.get('/api/home/getTableData')
    if (response.data.code === 200 && Array.isArray(response.data.data)) {
      tableData.value = response.data.data
    } else {
      console.error('Unexpected response data:', response.data)
    }
  } catch (error) {
    console.error('Failed to fetch table data:', error)
  }
})

response.data.code === 200:检查响应数据中的 code 是否等于 200。通常,200 表示请求成功。

Array.isArray(response.data.data):检查响应数据中的 data 是否是一个数组。

如果这两个条件都满足,则将 response.data.data 赋值给 tableData.value,否则输出错误信息。 成功渲染数据:

image.png

四.对axios进行二次封装

1. 封装 axios 请求

在 request.js 文件中,axios 被封装成一个通用的请求函数,并添加了请求和响应拦截器。

import axios from 'axios'
import { ElMessage } from 'element-plus'

const service = axios.create()

// 添加请求拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求之前做些什么
    return config
  },
  error => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
service.interceptors.response.use(
  res => {
    const { code, data, msg } = res.data
    if (code === 200) {
      return data
    } else {
      const NETWORK_ERROR = '网络错误'
      ElMessage.error(msg || NETWORK_ERROR)
      return Promise.reject(msg || NETWORK_ERROR)
    }
  }
)

function request(options) {
  options.method = options.method || 'get'
  return service(options)
}

export default request

2. 创建 API 模块

在 api.js 文件中,定义了一个 api 对象,用于封装具体的 API 请求。

import request from './request'

const api = {
  getTableData() {
    return request({ url: '/api/home/getTableData' })
  }
}
export default api

3. 挂载全局属性

在 main.js 文件中,将 api 挂载到 Vue 实例的全局属性中,以便在组件中使用。

import { createApp } from 'vue'
import App from './App.vue'
import "../src/assets/less/index.less"
import router from "./router"
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { createPinia } from 'pinia'
import "../src/api/mock"
**import api from '../src/api/api' // 确保路径正确**

const app = createApp(App)
const pinia = createPinia()

**app.config.globalProperties.$api = api**
app.use(ElementPlus)
app.use(router)
app.use(pinia)

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

**app.mount('#app')**

4. 在组件中使用封装后的 axios

在 Home.vue 文件中,通过 getCurrentInstance 获取 proxy,然后使用 proxy.$api.getTableData 来获取数据。

<script setup>
import { ref, onMounted, getCurrentInstance } from 'vue'

const getImageUrl = (user) => {
  return new URL(`../assets/images/${user}.png`, import.meta.url).href
}

const tableData = ref([])

const tableLabel = ref({
  name: "产品",
  todayBuy: "今日购买",
  monthBuy: "本月购买",
  totalBuy: "总购买",
})

const { proxy } = getCurrentInstance()

const getTableData = async () => {
  try {
    const data = await proxy.$api.getTableData()
    tableData.value = data
  } catch (error) {
    console.error('Failed to fetch table data:', error)
  }
}

// 使用 onMounted 钩子在组件挂载时调用 getTableData 函数
onMounted(getTableData)
</script>

home.js和mock.js和上一步一样不需要改变

最后效果:

image.png