[Vue practical project] General management system: encapsulating token operations and network requests

Table of contents

1 Overview

2. Encapsulate operations on tokens

3. Encapsulate axios


1 Overview

We have completed the login page previously:

[Vue Practical Project] General Management System: Login Page-CSDN Blog

Next we need to encapsulate the operations on the token and the network request operations. The reason why this part of the content needs to be encapsulated is because the token must be carried in all requests after we log in. It is impossible to write it by hand every time:

token=localStorage.getToken('token')
this.axios.post('接口API',参数+token)
          .then(res=>{
            //业务逻辑
          })

It is obviously not reusable to write it by hand every time. Once the token access logic or API address changes, it will have to be changed everywhere. So it is necessary to extract them and encapsulate them. The main content of this article is to explain how to encapsulate token operations and network requests.

2. Encapsulate operations on tokens

For an application system, after a user logs in, subsequent operations must perform permission verification, that is, a token must be brought when requesting the back-end interface. So we need to store the token and first encapsulate a set of operations on the token. Create a new setToken js under utils:

The content of setToken is very simple, which is to use localStorage to cache the token:

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

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

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

Since setToken is only needed when logging in, there is no need to introduce it into main.js so that it can be called globally. It can be introduced directly in the Login component and can be called in the Login component. Here we introduce it in another way. In addition to using relative paths and absolute paths to import, we can also use @ to import. @ will automatically help us locate the path of the resource.

import {setItem} from '@/utils/setToken.js'

Login component:

<script>
import {usernameAndPassWorldRule} from '../utils/validate.js'
//引入想要的操作token的方法
import {setToken} from '@/utils/setToken.js'
export default {
  data() {
    return {
      form: {
        username: "",
        password: "",
      },
      rules:{
        username:[{validator:usernameAndPassWorldRule,trigger:'blur'}],
        password:[{validator:usernameAndPassWorldRule,trigger:'blur'}]
      }
    };
  },
  methods:{
    login(form){
      this.$refs[form].validate((valid)=>{
        if(valid){
          console.log(this.form)
          this.$router.push('/home')
          this.axios.post('https://rapserver.sunmi.com/app/moc/340/login',this.form)
          .then(res=>{
            console.log(res)
            if(res.data.status===200){
              //使用引入的操作token的方法
              setToken('username',res.data.username)
              this.$message({message:res.data.message,type:'success'})
              this.$router.push('/home')
            }
          })
        }else{
          console.error(this.form)
        }
      })
    }
  }
};
</script>

Ok, at this step we have completed the encapsulation of token operations, but is this enough? Obviously it's not enough. There are at least two places that still need to be encapsulated:

  • Every network request must call axios to write a large list of addresses. Once the address changes, the global situation must be modified everywhere. Obviously, we should continue to encapsulate it here to avoid it being everywhere.
  • Subsequent requests must carry the token, so it is obviously necessary to encapsulate the action of putting the token in the request to avoid it being everywhere.

This is what we will continue to do next - encapsulate axios operations

3. Encapsulate axios

First let’s address the first of the two points mentioned earlier:

Every network request must call axios to write a large list of addresses. Once the address changes, the global situation must be modified everywhere. Obviously, we should continue to encapsulate it here to avoid it being everywhere.

This problem can be solved by setting up a proxy. Set the proxy in vue.config.js and write the URL prefix of the target service. By the way, enable cross-domain:

module.exports = {  
    devServer:{
      open:true,
      host:'localhost',
      //配置代理
      proxy:{
        '/api':{
          //目标地址
          target:'http://127.0.0.1:8081/api/',
          //开启跨域
          changeOrigin:true,
          pathRewrite:{
            '^/api':''
          }
        }
      }
    }
  }

Next, solve the second problem:

Subsequent requests must carry the token, so it is obviously necessary to encapsulate the action of putting the token in the request to avoid it being everywhere.

Encapsulate an axios tool js, service.js:

Service.js uses interceptors to intercept request and response, put token when the request is initiated, and handle errors when the response comes back:

import axios from "axios";
import { getToken } from "@/utils/setToken.js";
import { Message } from "element-ui";
const service= axios.create({
    baseURL:'/api',
    timeout:3000
})

//添加请求拦截器
service.interceptors.request.use((config)=>{
    //在请求之前做些什么(获取并设置token)
    config.headers['token']=getToken('token')
    return config
},(error)=>{
    return Promise.reject(error)
})

//响应拦截器
service.interceptors.response.use((response)=>{
    //对响应数据做些什么
    let{status,message}=response.data
    if(status!=200){
        //用elementUI的message来提升错误或者告警
        Message({message:message||'error',type:'warning'})
    }
    return response
},(error)=>{
    return Promise.reject(error)
})

export default service

service.js is used globally, so it is introduced in main.js:

import Vue from 'vue'
import App from './App.vue'
// import '../plugins/element.js'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

import 'font-awesome/css/font-awesome.min.css'
// import axios from 'axios'
import router from './router'

import service from './utils/service';

Vue.use(ElementUI)
//挂载到原型,可以在全局使用
// Vue.prototype.axios=axios
Vue.prototype.service=service;
Vue.config.productionTip = false

new Vue({
  //挂在router
  router,
  render: h => h(App),
}).$mount('#app')

Finally, let’s change the Login component and use setToken.js and service.js completely:

<template>
  <div class="login">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>通用后台管理系统</span>
      </div>
      <el-form
        label-width="80px"
        :model="form"
        ref="form"
        :rules="rules"
      >
        <el-form-item label="用户名" prop="username">
          <el-input v-model="form.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="form.password"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="login('form')">登录</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import {usernameAndPassWorldRule} from '../utils/validate.js'
//引入想要的操作token的方法
import {setToken} from '@/utils/setToken.js'
export default {
  data() {
    return {
      form: {
        username: "",
        password: "",
      },
      rules:{
        username:[{validator:usernameAndPassWorldRule,trigger:'blur'}],
        password:[{validator:usernameAndPassWorldRule,trigger:'blur'}]
      }
    };
  },
  methods:{
    login(form){
      this.$refs[form].validate((valid)=>{
        if(valid){
          console.log(this.form)
          this.service.post('/login',this.form)
          .then(res=>{
            console.log(res.status)
            if(res.status===200){
              setToken('username',res.data.username)
              setToken('token',res.data.token)
              this.$router.push('/home')

            }
          })
        }else{
          console.error(this.form)
        }
      })
    }
  }
};
</script>

<style lang="less">
.login{
  width: 100%;
  height:100%;
  position: absolute;
  background: #409EFF;
  .box-card{
    width:450px;
    margin: 200px auto;
    .el-card__header{
      font-size: 30px;
    }
    .el-button{
      width: 100%;
    }

  }
}
</style>

Guess you like

Origin blog.csdn.net/Joker_ZJN/article/details/134388945