1.axios攔截
axios攔截就是axios的二次封裝,這樣便於權限管理和統一異常處理,全局攔截器可以根據接口錯誤碼進行統一處理,而不需要再每一個接口內部進行控制,第二個好處就是,可以做全局的loading效果,如果不在全局做,你就要在每一個接口前顯示loading,接口結束進行關閉,不便於代碼維護,前端儘可能的去統一管理代碼。
參考文章:
https://hooray.github.io/posts/1059e373/
https://juejin.im/post/5bab739af265da0aa3593177
https://segmentfault.com/a/1190000008383094
https://zhuanlan.zhihu.com/p/33918784
https://blog.csdn.net/qq_36575992/article/details/80338538
https://blog.csdn.net/qq_38145702/article/details/81558816
https://segmentfault.com/q/1010000017347607/a-1020000017350518
https://blog.csdn.net/well2049/article/details/85003062
https://blog.csdn.net/rickiyeat/article/details/77030124
https://blog.csdn.net/sjn0503/article/details/74729300
https://blog.csdn.net/qq_33207292/article/details/72867211
https://blog.csdn.net/moxiaoya1314/article/details/73650751
2.Express設置cors
1.installation
npm install cors
2.Usage
//1.simple usage(Enable All CORS Requests)
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
//2.Enable CORS for a Single Route
var express = require('express')
var cors = require('cors')
var app = express()
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
//3.Configuring CORS
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
更多介紹可以參考文章:
http://expressjs.com/en/resources/middleware/cors.html#installation
https://www.jianshu.com/p/f650dfad5574
https://blog.csdn.net/sunq1982/article/details/77887655
https://www.jianshu.com/p/af2cad6d91fb
3.Vue中代理設置vue.config.js
我們可以在服務端進行設置跨域,我們在前端也可以設置代理,比如我們的Vue的端口是8080,後端的端口8000,這時就涉及到跨域,要進行代理設置,我們在vue.config.js中設置代碼是:
module.exports = {
publicPath:'/',
devServer:{
open: true,
host: 'localhost',
port: 8080,
https: false,
hotOnly: false,
proxy:{
'/api':{
target:'http://localhost:8000/api',
changOrigin: true, //允許跨域
pathRewrite:{
'^/api':''
}
}
}
}
}
參考文章:
https://blog.csdn.net/qq_40190624/article/details/85257610
https://blog.csdn.net/weixin_38201500/article/details/84791835
https://segmentfault.com/a/1190000014474361
https://segmentfault.com/a/1190000016602951
https://darknesschaser.github.io/2018/07/26/vue%E5%85%A8%E5%AE%B6%E6%A1%B6%E9%85%8D%E7%BD%AEwebpack%E5%8F%8D%E4%BB%A3/?tdsourcetag=s_pcqq_aiomsg
4.Vuex再學習
參考imooc課程。
Vuex應用場景
1.多個視圖依賴於同一狀態(多組件之間狀態共享,讀狀態的作用)
2.來自不同視圖的行爲需要改變同一個狀態(不同組件可以改變同一狀態,改狀態的作用)
Vuex的組成介紹
1.state:數據倉庫
State在Vuex中代表的是數據的來源,Vuex所有數據都會存儲在State中,是數據的唯一來源。
2.getter:原來獲取數據
可類比Vuex中的computed屬性,對state中數據進行一些操作
3.Mutation:用來修改數據
Mutation的操作是同步的,異步的話會有很大的麻煩,Mutation本質上也是一個function
4.Action:用來提交mutation
Action可以進行異步的操作
安裝Vuex
1.安裝vuex包:npm install vuex
2.創建vuex實例:new Vuex.store()
3.main.js中將vuex實例掛載到vue對象上
Vuex使用
1.獲取Vuex中state的值(例如state中的count)
{{this.$store.state.count}}
2.修改state中的值
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state:{
city:'上海'
},
mutations:{
changeCity(state,city){
state.city = city
}
},
action:{
changeCity(ctx,city){
ctx.commit('changeCity',city)
}
});
Vue文件中如果修改Vuex
最原始寫法:this.$store.dispatch('changeCity',city) 使用dispatch觸發一個changeCity函數
或者直接使用mutations中commit:this.$store.commit('changeCity',city)
5.token和jwt
身份認證的兩種方式
1.基於cookie
基於cookie的服務端認證,就是我們所熟知session,在服務端生成用戶相關的 session 數據,而發給客戶端 sesssion_id 存放到 cookie 中,這樣用客戶端請求時帶上 session_id 就可以驗證服務器端是否存在 session 數據,以此完成用戶認證。
2.基於Token令牌
基於token的用戶認證是一種服務端無狀態的認證方式,服務端不用存放token數據。用戶驗證後,服務端生成一個token(hash或encrypt)發給客戶端,客戶端可以放到cookie或localStorage(sessionStorage)中,每次請求時在Header中帶上token,服務端受到token通過驗證後即可確認用戶身份。
JWT的組成
JWT的本質實際上就是一個字符串,它有三部分組成頭部+載荷+簽名。
// 1.Header
{
"alg": "HS256",//所使用的簽名算法
"typ": "JWT"
}
// 2.Payload
{
//該JWT的簽發者
"iss": "luffy",
// 這個JWT是什麼時候簽發的
"iat":1441593502,
//什麼時候過期,這是一個時間戳
"exp": 1441594722,
// 接收JWT的一方
"aud":"www.youdao.com",
// JWT所面向的用戶
"sub":"[email protected]",
// 上面是JWT標準定義的一些字段,除此之外還可以私人定義一些字段
"form_user": "fsdfds"
}
// 3.Signature 簽名
將上面兩個對象進行base64編碼之後用.進行連接,然後通過HS256算法進行加密就形成了簽名,一般需要加上我們提供的一個密匙,例如secretKey:'name_luffy'
const base64url = require('base64url')
const base64header = base64url(JSON.stringify(header));
const base64payload = base64url(JSON.stringify(payload));
const secretKey = 'name_luffy';
const signature = HS256(`${base64header}.${base64payload}`,secretKey);
// JWT
// 最後就形成了我們所需要的JWT:
const JWT = base64header + "." + base64payload + "." + signature;
// 它長下面這個樣子:
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
JWT的工作原理
前後端如何用這個東西做身份驗證
接下來要詳細的說如何使用jwt來進行前後端的身份驗證了,具體思路如下:
用戶登錄註冊的邏輯不需要身份驗證,因爲沒有用戶的身份信息和登錄狀態;
用戶登錄之後後端生成token並返給前端,前端拿到token之後將token緩存在本地,可以使localStorage也可以是cookie,以便接下來使用。。
其他內容涉及到前後端交互的都需要前端把認證的token信息放在請求頭部傳給後端
後端收到請求先校驗token,如果token合法(也就是token正確且沒過期),則執行next(),否則直接返回401以及對應的message。
token登陸的具體實現細節
查看參考資料:https://juejin.im/post/5b06c6baf265da0db4791805
6.Vue中template中嵌套template
<template>
<el-row class="menu_page">
<el-col>
<el-menu
mode="vertical"
background-color="#324057"
text-color="#fff"
active-text-color="#409eff"
class="el-menu-vertical-demo">
<!--左側-首頁-->
<router-link to="/home">
<el-menu-item index="0">
<i class="el-icon-s-home"></i>
<span slot="title">首頁</span>
</el-menu-item>
</router-link>
<!--用戶管理和信息管理-->
<template v-for="item in items" >
<el-submenu v-if="item.children" :index="item.path" :key="item.path">
<template slot="title">
<i :class="'fa fa-margin '+item.icon"></i>
<span slot="title">{{item.name}}</span>
</template>
<router-link v-for="(citem,cindex) in item.children"
:to="citem.path" :key="cindex">
<el-menu-item
:index='citem.path'>
<span slot="title">{{citem.name}}</span>
</el-menu-item>
</router-link>
</el-submenu>
</template>
</el-menu>
</el-col>
</el-row>
</template>
<script>
export default {
name: "leftmenu",
data() {
return {
items: [
{
icon: "el-icon-user",
name: "用戶管理",
path: "fund", //設置:key
children: [{ path: "foundlist", name: "用戶信息" }]
},
{
icon: "el-icon-edit",
name: "信息管理",
path: "info",
children: [{ path: "infoshow", name: "個人信息" }]
}
]
};
}
};
</script>
<style scoped>
.menu_page {
position: fixed;
top: 60px;
left: 0;
min-height: 100%;
background-color: #324057;
z-index: 99;
}
.el-menu {
border: none;
}
.fa-margin {
margin-right: 5px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 180px;
min-height: 400px;
}
.el-menu-vertical-demo {
width: 35px;
}
.el-submenu .el-menu-item {
min-width: 180px;
}
.hiddenDropdown,
.hiddenDropname {
display: none;
}
a {
text-decoration: none;
}
</style>
把中間的template標籤改成div效果是一樣的,用template有什麼別的作用嗎?
回答:template不會渲染成元素,用div的話會被渲染成元素。把if,show,for等語句抽取出來放在template上面,也就是和指令中的v-if/v-for一起用,把綁定的事件放在temlpate裏面的元素上,可以使html結構更加清晰,還可以改善一個標籤過長的情況。
參考文章: https://segmentfault.com/q/1010000010727886
更多參考資料:
https://segmentfault.com/a/1190000015718564
https://segmentfault.com/a/1190000014062679