前提: (1) 相關博文地址: SpringBoot + Vue + ElementUI 實現後臺管理系統模板 -- 前端篇(一):搭建基本環境:https://www.cnblogs.com/l-y-h/p/12930895.html SpringBoot + Vue + ElementUI 實現 ...
前提:
(1) 相關博文地址:
SpringBoot + Vue + ElementUI 實現後臺管理系統模板 -- 前端篇(一):搭建基本環境:https://www.cnblogs.com/l-y-h/p/12930895.html SpringBoot + Vue + ElementUI 實現後臺管理系統模板 -- 前端篇(二):引入 element-ui 定義基本頁面顯示:https://www.cnblogs.com/l-y-h/p/12935300.html
(2)代碼地址:
https://github.com/lyh-man/admin-vue-template.git
一、引入 js-cookie
1、簡介
為了保存 token 值,可以使用 cookie 或者 localStorage 或者 sessionStorage 保存。
此處採用 cookie 進行保存,所以引入 js-cookie 插件,用於操作 cookie。
2、token
(1)簡單理解一下 token 是什麼?
直譯為 “令牌”,是由服務端生成的一串字元串,作為客戶端進行請求的一個標識。
(2)token 一般用在什麼時候?
一般用於用戶第一次登錄系統時,服務端生成一個 token,返回給客戶端,客戶端下次請求時帶上這個 token 發送請求,不用再帶上用戶名和密碼,簡化了驗證操作。
(3)為什麼使用 token?
HTTP 協議是一種無狀態的協議,客戶端發送請求時,服務端並不知道是哪個客戶端在訪問。可以使用 用戶名以及密碼 唯一確定用戶身份,但是每次響應請求時都要驗證一下用戶,這就很煩。
可以使用 session 以及 sessionId 的方式去解決,當客戶登錄系統時,服務端驗證並生成一個記錄保存在 session 中,並將這條記錄的 id(即 sessionID) 返回給 客戶端,客戶端使用 cookie 或者 localStorage 保存,再次發送請求時,帶上這個 sessionID,服務端響應並找到對應的記錄進行驗證。
可以使用 token 的方式解決,當客戶登錄系統時,服務端驗證並返回一個 token 給客戶端,客戶端下次發送請求時,帶上這個 token,服務端驗證 token 即可。
(4)session 與 token 區別?
session 存儲是需要空間的(存儲用戶信息),伺服器需要單獨保存一份,以空間換時間。
token 可以不用存儲用戶信息,伺服器不用保存(解密 token 即可),以時間換空間。
3、安裝、引入 js-cookie
(1)npm 安裝 js-cookie
【使用 npm 安裝:】
npm install js-cookie
(2)引入 js-cookie
此處直接定義 一個 auth.js 並引入,使用時引入 該 js 文件即可。
也可使用 main.js 全局引用。
【在項目中引入 js-cookie:】 // 引入 token,此處直接引入,也可以在 main.js 中全局引入 import Cookies from 'js-cookie' // 設置 token 存儲的 key const TokenKey = 'Admin-Token' // 獲取 token export function getToken() { return Cookies.get(TokenKey) } // 設置 token export function setToken(token) { return Cookies.set(TokenKey, token) } // 移除 token export function removeToken() { return Cookies.remove(TokenKey) }
二、引入、封裝 axios
1、簡介
想要發送 ajax 請求,vue 項目中一般使用 axios,使用起來雖然簡單,但如果不進行統一封裝,隨著項目越來越大,冗餘代碼會急劇增加,所有需要對 axios 進行二次封裝,使各個組件間能夠復用 axios,簡化代碼。
【vue 引入 axios 並簡單使用 參考地址:】 https://www.cnblogs.com/l-y-h/p/11656129.html
2、封裝要求
統一 url 配置(可以與代理結合起來使用解決跨域問題)。
定義請求攔截器(request),比如:設置消息頭、設置 token 等。
定義響應攔截器(response),比如:統一錯誤處理、頁面重定向 等。
3、引入 axios
(1)npm 安裝 axios
【npm 安裝】
npm install axios
(2)引入 axios
此處直接定義 一個 httpRequest.js 引入,使用時引入 該 js 文件即可。
也可使用 main.js 全局引用。
import Vue from 'vue' import { getToken, removeToken } from '@/http/auth.js' import router from '@/router' import { Message } from 'element-ui' import axios from 'axios' // 創建 axios 實例 const http = axios.create({ // 統一 url 配置,定義訪問首碼 baseURL baseURL: '/api', // 定義請求超時時間 timeout: 10000, // 請求帶上 cookie withCredentials: true, // 定義消息頭 headers: { 'Content-Type': 'application/json; charset=utf-8' } }) // 定義請求攔截器 http.interceptors.request.use( config => { // 讓每個請求攜帶 token config.headers['Admin-Token'] = getToken() return config }, error => { Promise.reject(error) } ) // 定義響應攔截器 http.interceptors.response.use( response => { const res = response.data // 當 token 失效時,清除 cookie 保存的 token 值,並跳轉到登陸界面 if (res && res.code === 401) { removeToken() Message({ message: res.message, type: 'error', duration: 5000 }) router.push({ name: 'Login' }) } // 未找到頁面時,跳轉到 404 頁面 if (res && res.code === 404) { router.push({ name: '404' }) } return response }, error => { return Promise.reject(error) } ) export default http
(3)全局掛載 axios
在 main.js 中引入 httpRequest.js 文件,並全局掛載。
import http from '@/http/httpRequest.js' // 全局掛載 http(axios),使用的時候直接使用 this.$http 即可。 Vue.prototype.$http=http
(4)簡單寫個案例測試一下:(僅供參考)
後端:
定義一個 AuthController,用於返回 token。
其中:
@CrossOrigin 用來解決跨域(一般加上這個即可跨域)。如果此註解不生效,可以在前端配置代理來實現跨域。
package com.lyh.template.back.controller; import com.lyh.template.back.util.Result; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/auth") @CrossOrigin public class AuthController { @RequestMapping("/token") public Result getToken() { return Result.ok().data("token", "admin"); } }
如下,介面訪問正常(當然,使用 swagger 測試也一樣)。
前端:
修改代理,用於跨域。
在 vue.config.js 文件中進行配置,當路徑中出現 /api 時,會將其替換成 target 中的路徑。
而 target 路徑是從 配置文件中讀取的,生產環境與開發環境的 VUE_APP_URL 不同。
註:
開發環境時:
VUE_APP_URL=http://localhost:8000
生產環境時:
VUE_APP_URL=http://localhost:9000
module.exports = { lintOnSave: false, devServer: { port: process.env.NODE_ENV == "production" ? 8000 : 9000, proxy: { '/api': { target: process.env.VUE_APP_URL, // 允許跨域 changeOrigin: true, ws: true, pathRewrite: { '^/api': '' } } } } }
修改一下 Login 組件中的登陸方法,測試一下。
發送 /auth/token 請求時,會代理到 http://localhost:8000/auth/token。
登錄成功後,會列印返回數據,並跳轉到主界面。
methods: { // 提交表單 dataFormSubmit() { // TODO:登錄代碼邏輯待完善 // alert("登錄代碼邏輯未完善") this.$http({ url: '/auth/token', method: 'get' }).then(response => { console.log(response) this.$router.replace({name: 'Home'}) }) } }
三、引入、封裝 mock
1、簡介
項目開發的時候,有時候後端介面不給力,要是必須從後端獲取數據,沒有其他方式獲取數據,那就很蛋疼了(只能等後端介面正常,才可以繼續開發前端)。
mock 是一個數據模擬生成器,用於幫助前端獨立於後端進行開發,其模擬 ajax 並返回相應的數據,從而使前端不必依賴於後端介面,方便開發。
【vue關於mock的簡單使用 參考地址:】 https://www.cnblogs.com/l-y-h/p/11691110.html
2、封裝要求
定義不同的模塊,用於響應不同組件的請求。
可以方便、快捷的關閉某個模塊、或者某個請求的處理(關閉請求處理後,可以直接訪問後端介面)。
3、引入 mock
(1)npm 安裝 mock
【npm 安裝 mock:】
npm install mockjs
(2)引入 mock
定義一個 mock 文件夾以及統一處理入口 mock.js。
定義一個 fnCreate 方法 用來處理 mock。
其中:
第一個參數為 模塊名,需要通過 import 引入。
第二個參數為 是否開啟 mock ,true 為開啟,false 為關閉。
import Mock from 'mockjs' import * as login from './modules/login.js' // 可以通過 isOpen 參數設置是否攔截整個模塊的 mock 功能 fnCreate(login, true) /** * 創建mock模擬數據 * @param {*} mod 模塊 * @param {*} isOpen 是否開啟? */ function fnCreate(mod, isOpen = true) { if (isOpen) { for (var key in mod) { ((res) => { if (res.isOpen !== false) { Mock.mock(new RegExp(res.url), res.type, (opts) => { opts['data'] = opts.body ? JSON.parse(opts.body) : null delete opts.body console.log('\n') console.log('%cmock攔截, 請求: ', 'color:blue', opts) console.log('%cmock攔截, 響應: ', 'color:blue', res.data) return res.data }) } })(mod[key]() || {}) } } }
(3)定義功能子模塊
給不同的組件定義不同的模塊,用於區分不同的操作。
比如創建一個 login.js 用來處理 登錄、登出操作。
import Mock from 'mockjs' // 登錄 export function getToken() { return { // isOpen: false, url: 'api/auth/token', type: 'get', data: { 'msg': 'success', 'code': 0, 'expire': Mock.Random.natural(60 * 60 * 1, 60 * 60 * 12), 'token': Mock.Random.string('abcdefghijklmnopqrstuvwxyz0123456789', 32) } } }
(4)全局引入 mock 文件
在 main.js 中引入,可以控制引入時機,比如只在開發環境下生效。
// 非生產環境, 適配mockjs模擬數據 if (process.env.NODE_ENV !== 'production') { require('@/mock') }
(5)簡單測試一下。
開發環境運行時,登錄會觸發 mock ,在控制台列印數據。
(6)與後臺介面的區別。
使用 mock 返回數據 與 訪問後臺介面還是有區別的。
開發環境下,若想訪問後臺,
方式一:可以在 main.js 中將 引入 mock 文件的代碼註釋掉,就可以訪問了。
方式二:在 mock 的 fnCreate 方法中,將 isOpen 參數置為 false 即可(關閉 mock 功能)。
生產環境下,執行 dist 項目,可以通過 nginx 反向代理到後臺伺服器,進行訪問(後續項目部署時再補充)。