vue-element-admin登陆模块和axios踩坑


最近在做公司的一个后台管理项目,用了vue admin来搭建项目的前端,本人也是个vue的新手,很多都不太理解,各种百度,才搞懂了整个登陆流程接口的替换,因此在此记录一下。

所有的重点我都会在代码中的注释里说明。

一、登陆接口的替换

//这段代码是src/api/user.js中的代码
import request from '@/utils/request'

export function login(data) {
  return request({
    // 这里替换成自己的登陆接口,下面的也是一样
    url: '/login',
    method: 'post',
    data
  })
}

export function getInfo(otherQuery) {
  return request({
    url: '/getInfo',
    method: 'get',
    params: otherQuery
  })
}

export function logout() {
  return request({
    url: '/vue-admin-template/user/logout',
    method: 'post'
  })
}

login()方法那里,url只需要替换成自己登陆接口地址就行,不要带上接口的IP地址或者域名。然后,顶部我们注意到,有一个import request from '@/utils/request',这是request文件,也就是我们request方法的定义,让我们来看下文件里的一段代码:

const service = axios.create({
  // 这里替换成自己接口的服务器地址,并且把.env.development中的VUE_APP_BASE_API参数置为空
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  timeout: 5000 // request timeout
})

可以看到,baseURL那里需要换成自己的接口地址才算全部替换完成。

二、接口调用以及response的处理

可能有些小伙伴会觉得奇怪,怎么换了接口还是登陆不进去页面呢?这是因为还没调用接口方法。
整个登陆流程的接口调用,包括登陆、获取用户信息、登出等步骤,都在@/store/modules/user中进行了调用,而各种登陆信息的存储,也都在此文件中操作。我们来看下代码:

import { login, logout, getInfo } from '@/api/user'//这里便引用了我们说的接口方法文件,即第一点登陆接口替换那部分文件代码
import { getToken, setToken, removeToken } from '@/utils/auth'//这个文件不用管,是已经封装好的关于token的几个方法
import router, { resetRouter } from '@/router'
//state和mutations里按需进行删除和添加,比如说,如果你需要存储一个用户id字段用于后续接口,直接添加进来,用this.$store.state.user.id便可在后续文件中引用
const state = {
  token: getToken(),
  name: '',
  avatar: '',
  introduction: '',
  roles: []
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_INTRODUCTION: (state, introduction) => {
    state.introduction = introduction
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  }
}

const actions = {
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      //此处的login()方法便是@/api/user中的login()方法,username和password根据后台提供的接口进行参数替换
      login({ username: username.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {//如果前期不需要用户信息,可直接把大括号外部注释掉,留大括号里的内容(即const开头那部分内容),data用假数据
        const { data } = response

        if (!data) {
          reject('Verification failed, please Login again.')
        }

        const { roles, name, avatar, introduction } = data

        if (!roles || roles.length <= 0) {
          reject('getInfo: roles must be a non-null array!')
        }

        commit('SET_ROLES', roles)
        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_INTRODUCTION', introduction)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  logout({ commit, state, dispatch }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {//这里也是同理,不需要便注释,留下大括号内的内容同样可以清除token登出
        commit('SET_TOKEN', '')
        commit('SET_ROLES', [])
        removeToken()
        resetRouter()

        dispatch('tagsView/delAllViews', null, { root: true })

        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  resetToken({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '')
      commit('SET_ROLES', [])
      removeToken()
      resolve()
    })
  },
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

登陆流程的接口调用流程改完之后,我们便可以进去首页了。

如果还是进不去,便到login.vue和@/utils/validate中修改验证信息即可。

接下来是返回数据response的处理。我们先来看看request文件的剩余部分:

service.interceptors.request.use(
  config => {
    // 这里是将获取到的token放在请求头里
    if (store.getters.token) {
      // 每一个request都将带上token,这里的X-Token可根据后端的设定或者浏览器的要求来改
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    console.log(error) 
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  response => {
    const res = response.data
    // 这里记得将code改为自己的code
    if (res.code !== 20000) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        // 这是请求的时长,可以设置的长一些,不然请求时间久的话,超过这个时长就会报错
        duration: 5 * 1000
      })

      // 这里也可按自己的需要去更改
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  error => {
    console.log('err' + error) 
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

需要注意的是,上述代码中的response是包含了请求头在内的response,而res只是取了数据部分,如果不进行修改,后续接口的调用是获取不到headers的。如果后续需要获取请求头,也要在这里按需修改。

三、其他接口的调用及axios踩坑

上面已经将登陆部分接口相关的内容全部讲完,接下来是讲述除登陆以外的接口我们要怎么去调用。
其实看完整的vue-element-admin模版便可以发现,所有的接口信息都储存在@/api之下的js文件中,而vue文件中如果要调用的话,则可按以下步骤来:

//@/api/article是api文件夹下的article.js文件,存放了fetchList这个接口方法,用import引入这个方法
import { fetchList } from '@/api/article'

methods: {
    getList() {
      this.listLoading = true
      //这里便可引用fetchList方法进行接口调用
      fetchList(this.listQuery).then(response => {
        this.list = response.data.items
        this.total = response.data.total
        this.listLoading = false
      })
    }
  }

看完接口调用步骤之后,我要说一下新手容易踩的一个axios坑,拿登陆和用户信息接口为例来讲:

export function login(data) {
  return request({
    url: '/vue-element-admin/user/login',
    method: 'post',
    data
  })
}

export function getInfo(token) {
  return request({
    url: '/vue-element-admin/user/info',
    method: 'get',
    params: { token }
  })
}

我们可以看到,登陆接口是post方法,而参数传递如果只是一个data的话,其实是相当于用data:data这样的形式来传递的参数。

而在axios中,data:xxx是表示传递的参数不采用拼接的方式传递,params:xxx则相反。

这点让还是新手的我踩了不少坑,因为我在这里特别标注以下,以防有像我这样的新手再踩坑。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM