Vue+element搭建后台管理系统-五、网络请求封装-vue封装axiaos

上一章我们详解了项目的架构目录,这一章主要学习对接口的封装。

网络请求封装是每个前端项目必不可少的一项,有利于方便统一管理,比如在请求头统一加上后台校验数据,这样就没必要在每个接口中都写一遍了嘛,这也是面向对象编程的一个好的提现。

我们这次选用的是axios插件,这个插件优点还是蛮多的,支持promise,可以拦截请求和拦截响应,客户端支持防御XSRF攻击等等,那么我们就开始吧。

一、安装axios

老规矩,在控制台中输入:

npm install axios -S

二、对axiaos做封装

我们在request目录的index.js文件中,

导入axiaos插件,主角。

导入用到的element-ui中的Message弹窗组件,主要用作提示报错,如:接口请求报错了,可以在响应拦截中弹窗提示相应信息。

导入store,用于设置全局的状态管理,比如常用到的用户信息,站点管理这些。

导入auth,封装有获取token方法的插件,如:获取浏览器缓存中的token信息。

导入路由router,用于路由跳转,如:后台返回登录信息过期,那么我们在请求响应拦截捕获到了,然后我们就可以直接做路由跳转到登录页面了。

并写入相应的请求拦截和响应拦截。

import axios from 'axios'
import { Message } from 'element-ui' //element弹窗
import store from '@/store' //登录信息
import { getToken } from '@/utils/helper/auth.js' //获取token
import Router from '@/router/index.js' //路由对象

const service = axios.create({
    timeout: 10000,
})

// request interceptor
//请求拦截
service.interceptors.request.use(
    (config) => {
        //header存放token-一般接口要求
        config.headers['token'] = getToken()
        //设置请求接口
        service.prototype.requestUrl = config.url
        return config
    },
    (error) => {
        // do something with request error
        console.log(error) // for debug
        return Promise.reject(error)
    }
)

// response interceptor
//响应拦截
service.interceptors.response.use(
    /**
     * 这里会返回http请求的信息,如数据、状态码
     */
    (data) => {
        data = data.data
        let res = {}

        if (data.code == '0') {
            console.log('接口请求数据正常')
        } else if (data.code == 201 || data.code == '9001') {
            Message({
                message: '账号信息已过期,请重新登录',
                type: 'warning',
            })
            //清空用户信息
            store.commit('user/logout')
            Router.push({ path: '/login' })
        } else {
            Message({
                message: data.msg,
                type: 'error',
            })
        }

        // 处理返回格式-自定义返回所有数据或数据包裹指定数据
        // eslint-disable-next-line no-prototype-builtins
        if (data.hasOwnProperty('data') && data.data != null && !data.total && service.prototype.requestUrl.indexOf('auth') == -1) {
            res = data.data
        } else {
            res = data
        }

        return res
    },
    (error) => {
        console.log('err' + error) // for debug
        Message({
            message: error.message,
            type: 'error',
            duration: 5 * 1000,
        })
        return Promise.reject(error)
    }
)

export default service

加好上面的内容后,补充一下需要导入的内容。在utils文件夹下创建helper文件夹,然后新建auth.js文件,加入下面获取token的方法。

utils/helper/auth.js内容:

const TokenKey = 'token'

export function getToken() {
  return localStorage.getItem(TokenKey)
}

export function setToken(token) {
  return localStorage.setItem(TokenKey, token)
}

export function removeToken() {
  return localStorage.removeItem(TokenKey)
}

补充一下store中的内容:

store/modules/user.js内容:

export default {
    namespaced: true,
    state: {
        userInfo: {
            id: null,
            account: '',
            realName: '',
            companies: '',
            sites: null,
        },
    },
    mutations: {
        setUserInfo(state, param) {
            state.userInfo = param
        },
        logout(state, param) {
            state.userInfo = param
        },
    },
}

补充好上面的内容后,然后做一下全局配置,这样可以在vue文件中通过this调用了。

三、全局配置

api目录下创建index.js文件

导入Vue,通过原型继承,实现全局注册。

导入string的toLowerCaseBar,这个方法是用来将小写驼峰的字符串转成小写横杆的字符串,比如:getDataApi转成get-data-api,主要的作用是做一个请求方法的统一管理。

并写入下面内容:

import Vue from 'vue'
import { toLowerCaseBar } from '@/utils/helper/string.js' // 格式(小写驼峰)转 格式(小写横杠)

/**
 * 页面调用API目录方法
 * @func ajax
 * @param {String} route 请求路径
 * @param {Object} param 接口参数
 */
const ajax = (route, param) => {
    let arr = route.split('/') // 目录 -> 文件 -> 方法
    // 获取组s件
    let components = require('./' + toLowerCaseBar(arr[0]) + '/' + toLowerCaseBar(arr[1]) + '.js')[arr[2]]
    return components(param)
}

/**
 * 页面调用API目录方法
 * @func ajax
 * @param {String} route 请求路径
 * @param {Object} param 接口参数
 */
Vue.prototype.$ajax = ajax

export default ajax

补充一下上述导入的string.js文件,同样在utils文件夹下的helper文件夹,创建string.js,为啥叫string.js呢?

主要类似一个类吧,主要应用于字符串类型的操作,字符串截取,字符串转换等等。

然后添加以下代码:

/**
 * 格式(小写驼峰)转 格式(小写横杠)
 * @func toLowerCaseBar
 */
export const toLowerCaseBar = (data) => {
    let res = ''

    if (data) {
        res = data.replace(/[A-Z]/g, (item) => `-${item.toLowerCase()}`)
    }

    return res
}

封装的工作做好了,然后在main.js文件中做一下全局导入,通过import 导入api下的index.js文件即可。

....
import 'element-ui/lib/theme-chalk/index.css' //样式文件一定要引入

import './api/index.js'
//载入路由
....

四、添加mock数据-测试

现在我们在搭建框架的过程中,后台应该还没出接口供我们测试,那么就需要我们去造数据。

打开cmd,安装我们所用到的工具,mockJS

npm install --save-save mockjs

然后我们在src目录下创建service文件夹,创建两个文件,index.js,test.mock.js主要用来存放虚拟接口数据的。

 

 index.js文件代码如下:

import Mock from 'mockjs'

//入口文件
Mock.setup({
    timeout: '500-800',
})

const context = require.context('./', true, /\.mock.js$/)

context.keys().forEach((key) => {
    Object.keys(context(key)).forEach((paramKey) => {
        Mock.mock(...context(key)[paramKey])
    })
})
export default context

这个文件的作用将service下的每个数据模块导入然后再全局导出,这样我们在开发的时候,就可以做虚拟数据的按模块独立出来。例如下面的test.mock.js文件,可以作为一部分接口数据。

test.mock.js代码如下:

import Mock from 'mockjs'

const { Random } = Mock

export default [
    RegExp('/login.*'),
    'get',
    {
        'range|50-100': 50,
        'data|10': [
            {
                // 唯一 ID
                id: '@guid()',
                // 生成一个中文名字
                cname: '@cname()',
                // 生成一个 url
                url: '@url()',
                // 生成一个地址
                county: Mock.mock('@county(true)'),
                // 从数组中随机选择一个值
                'array|1': ['A', 'B', 'C', 'D', 'E'],
                // 随机生成一个时间
                time: '@datetime()',
                // 生成一张图片
                image: Random.dataImage('200x100', 'Mock Image'),
            },
        ],
    },
]

做好之后,在main.js文件中导入:

做好全局导入之后,我们就可以通过请求来做测试了。

简单写一个请求数据的方法,在api文件夹下创建login文件夹,然后在login文件夹下创建auth-api.js,添加下面内容:

导入request,前面封装的网络请求方法

导入url,全局配置文件中的请求域。config.index.js代码如下:(域名记得换成自己本机nodeJS运行服务的域名)

/* eslint-disable no-undef */
const CONFIG = {
    //开发环境
    development: {
        url: 'http://192.168.0.101:8080', //本机ip地址域名
    },
    //生产环境
    production: {
        url: 'https://getman.cn/mock', //生产环境的请求域名
    }
}
export default CONFIG[process.env.NODE_ENV]

auth-api.js代码入下:

import request from '@/utils/request/index.js'
import config from '@/config/config.index.js'

/**
 * @description 登录
 * @param {JSON} param
 * @returns
 */
export const loginApi = (param) => {
    return request({
        method: 'post', // 请求方式: GET、POST
        url: config.url + '/login',
        data: param, // 请求参数
    }).then((res) => {
        return new Promise((resolve) => {
            resolve(res)
        })
    })
}

然后我们在App.vue中添加一个点击方法,用作调起请求用的。

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <el-button type="primary" @click="getData">测试按钮</el-button>
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  methods: {
      getData() {
          this.$ajax('login/authApi/loginApi', {}).then(res => {
              console.log(res)
          }).catch(rej => {
              console.log(rej)
          })
      }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 点击测试按钮,就可以正常调用网络请求的方法。

 

 本章内容就到这里结束吧,下一章为大家讲一下如何去实现权限管理。

posted @ 2022-04-18 17:51  padding2020  阅读(662)  评论(0编辑  收藏  举报
想了解更多的,大家也可以关注我的公众号:padding2020