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":"any@126.com",
// 上面是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