springboot+vue实现前后端分离之前端vue部分(spring boot 2.5.4/vue.js 3.2.4)

一,功能演示:

      无后端服务时:
 
提示信息自动关闭后:
服务端返回401访问无授权时,会跳转到login页面
如果登录错误:
登录成功,跳转回home页面,可以看到相应的用户信息:
查看保存到local storage中的token:

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,前、后端项目的代码地址

前端:
https://gitee.com/liuhongdi/jwtweb
后端:
https://gitee.com/liuhongdi/jwtdemo

 说明:后端项目的说明请参见:

https://www.cnblogs.com/architectforest/p/15185416.html

三,vue.js安装需要用到的依赖库

1,安装axios
查看当前版本
liuhongdi@lhdpc:/data/vue/demo1$ npm list axios
demo1@0.1.0 /data/vue/demo1
└── (empty)
 安装
liuhongdi@lhdpc:/data/vue/demo1$ npm install axios -S
 
added 1 package in 6s
查看安装后版本
liuhongdi@lhdpc:/data/vue/demo1$ npm list axios
demo1@0.1.0 /data/vue/demo1
└── axios@0.21.1
2,安装element-plus
查看当前版本
liuhongdi@lhdpc:/data/vue/demo1$ npm list element-plus
demo1@0.1.0 /data/vue/demo1
└── (empty)
 安装
liuhongdi@lhdpc:/data/vue/demo1$ npm install element-plus --save
 
added 15 packages, and changed 4 packages in 10s

查看安装后版本

liuhongdi@lhdpc:/data/vue/demo1$ npm list element-plus
demo1@0.1.0 /data/vue/demo1
└── element-plus@1.0.2-beta.71
3,安装vue-router
 查看当前版本
liuhongdi@lhdpc:/data/vue/demo1$ npm list vue-router@next
demo1@0.1.0 /data/vue/demo1
└── (empty)
 安装
liuhongdi@lhdpc:/data/vue/demo1$ npm install vue-router@next --save
 
added 2 packages in 4s
查看安装后版本
liuhongdi@lhdpc:/data/vue/demo1$ npm list vue-router@next
demo1@0.1.0 /data/vue/demo1
└── vue-router@4.0.11 

四,js代码说明:

1,App.vue

<template>
  <router-view />
</template>

<script>
export default {
  name: 'App',
  components: {
  }
}
</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>

2,main.js

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import router from './router/router'
//element-plus 的中文化
import locale from 'element-plus/lib/locale/lang/zh-cn'  //element-plus

//设置网页标题
router.beforeEach((to, from, next) => {
    //路由发生变化修改页面title
    if (to.meta.title) {
        document.title = to.meta.title+"--网站名称"
    }
    next()
})

//启动app
const app = createApp(App)
app.use(ElementPlus,{locale})
app.use(router)
app.mount('#app')

3,router/router.js

import {createRouter, createWebHashHistory} from 'vue-router';
import Home from "../views/Home.vue";
import Login from "../views/Login.vue";

//路由
let routes = [
    {
        path: "/",
        redirect: '/home'
    },
    { path: "/login", name: "login",meta:{title:"登录",top:"0"},component: Login,
    },
    { path: "/home", name: "home",meta:{title:"个人页",top:"0"},component: Home,
    },
]

// Vue-router新版本中,需要使用createRouter来创建路由
export default  createRouter({
    // 指定路由的模式,此处使用的是hash模式
    history: createWebHashHistory(),
    routes
})

4,api/axios.js

import axios from 'axios'
import { ElMessage } from "element-plus";
import router from "../router/router"

let config = {
    timeout:10000,
};

const _axios = axios.create(config);
_axios.interceptors.request.use(
    function(config) {
        // Do something before request is sent
        if (localStorage.getItem('token')) {
            config.headers.Authorization = "Bearer "+localStorage.getItem('token');
        }
      return config;
    },
    function(error) {
      // Do something with request error
      return Promise.reject(error);
    }
);

// Add a response interceptor
_axios.interceptors.response.use(
    function(response) {
        let code = response.data.code;
        if (code == '401') {
            //现在跳转去登录
            router.push({ path: '/login' });
        }
      return response;
    },
    function(error) {
      // Do something with response error
        if (error.response.status) {
            //alert(error.response.status);
            switch (error.response.status) {
                // 401: 未登录
                // 未登录则跳转登录页面,并携带当前页面的路径
                // 在登录成功后返回当前页面,这一步需要在登录页操作。
                case 401:
                    router.push({ path: '/login' });
                    break;
                // 403 token过期
                // 登录过期对用户进行提示
                // 清除本地token和清空vuex中token对象
                // 跳转登录页面
                case 403:
                    ElMessage.error("登录过期,请重新登录");
                    // 清除token
                    localStorage.removeItem('token')
                    // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
                    setTimeout(() => {
                        router.push({ path: '/login' });
                    }, 1000)
                    break;
                // 404请求不存在
                case 404:
                    ElMessage.error("网络请求不存在,404错误");
                    break;
                // 500服务端错误
                case 500:
                    ElMessage.error("服务端有故障,500错误");
                    break;
                // 其他错误,直接抛出错误提示
                default:
                    //alert("default:"+error.response.data.message);
                    var tip = "";
                    if (typeof(error.response.data.message) == "undefined") {
                        //alert(error);
                        tip = error.toString();
                    } else {
                        tip = error.response.data.message;
                    }
                    ElMessage.error(tip);
                    break;
            }
            return Promise.reject(error.response)
        }
    }
);

/**
 * get方法,对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function get (url, params) {
  return new Promise((resolve, reject) => {
    _axios.get(url, {
      params: params,
    }).then(res => {
      resolve(res.data)
    }).catch(err => {
      reject(err.data)
    })
  })
}
//post
export function postForm (url, params) {
  //axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
  return new Promise((resolve, reject) => {
    _axios.post(url, params,{headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    }})
        .then(res => {
          resolve(res.data)
        })
        .catch(err => {
            console.log("api error:");
            console.log(err);
            //alert(err);
          reject(err.data)
        })
  })
}

//用json格式post提交
export function postJson (url, params) {
  return new Promise((resolve, reject) => {
    _axios.post(url, JSON.stringify(params))
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        reject(err.data)
      })
  })
}

5,其他代码可参见gitee

五,查看项目中第三方库的版本

liuhongdi@lhdpc:/data/vue/jwtweb$ npm list 
jwtweb@0.1.0 /data/vue/jwtweb
├── @vue/cli-plugin-babel@4.5.13
├── @vue/cli-plugin-eslint@4.5.13
├── @vue/cli-service@4.5.13
├── @vue/compiler-sfc@3.2.4
├── axios@0.21.1
├── babel-eslint@10.1.0
├── core-js@3.16.2
├── element-plus@1.0.2-beta.71
├── eslint-plugin-vue@7.16.0
├── eslint@6.8.0
├── vue-router@4.0.11
└── vue@3.2.4

六,查看vue/cli及node的版本:

liuhongdi@lhdpc:/data/vue/jwtweb$ vue --version
@vue/cli 4.5.13
liuhongdi@lhdpc:/data/vue/jwtweb$ node -v
v14.17.1
原文地址:https://www.cnblogs.com/architectforest/p/15185275.html