vue拦截器和vue-cookies
vue 拦截器
假设现在有这么一个需求,页面上有些url需要登录之后才能访问,没有登录访问自动跳转到登录页面。之前项目前后端未分离的时候,直接从session中去匹配,能匹配到则render页面,没匹配成功表示没有登录则redirect到login页面。现在项目统一采用vue + restframework的方式,写vue的感觉就像是在写后台了,哈哈。在vue就能做到这个功能,但是需要后台也做最后一层屏障。因为vue是根据浏览器的cookie是否有token,后台需要判断这个token是不是合法的,至于cookie中没有token就更加走不到后台了。
main.js
在main.js底部加如下代码
router.beforeEach(function (to, from, next) {
if(to.meta.requireAuth){
if (store.state.token) {
next()
} else {
next({name: 'login',query: {next_url: to.fullPath}})
}
}else{
next()
}
});
index.js
在router的index.js里的每个路由加上meta:{requireAuth:true}
, meta
是固定的,requireAuth
是随意取的
export default new Router({
routes: [
{
path: '/index',
name: 'index',
component: index,
meta:{
requireAuth:true
}
},
{
path: '/course/:id',
name: 'course',
component: course
}]
上述表述index页面需要登录才能查看
vue-cookies
安装 npm install vue-cookies --save
store目录下的store.js的内容
import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'
Vue.use(Vuex);
export default new Vuex.Store({
// 组件中通过 this.$store.state.username 调用
state: {
token:Cookie.get('token'),
},
mutations: {
saveToken(state, token){
state.token = token;
Cookie.set('token', token, '20min')
},
clearToken(state){
Cookie.remove('token');
state.token = null;
}
}
})
在main.js直接import store from './store/store'
把store挂载到Vue实例中即可。
axios发送请求
安装npm install axios
在main.js加上两句
import axios from 'axios'
Vue.prototype.$axios = axios;
Login.vue组件
<template>
<div>
<div v-if="this.$store.state.token">
<h3>登录成功</h3>
</div>
<div v-else>
<h3>登录页面</h3>
<input type="text" v-model="name"/>
<input type="password" v-model="pwd"/>
<button @click="login">登录</button>
</div>
</div>
</template>
<script>
export default {
name: 'Login',
data () {
return {
name:'',
pwd:''
}
},
computed:{
},
methods:{
login(){
var that = this;
this.$axios.request({
url:'http://127.0.0.1:8000/api/v1/account/login/',
method:'post',
data:{
name:this.name,
pwd:this.pwd
}
}).then(function (ret) {
if (ret.data.code === 1000){
that.$store.commit('saveToken', ret.data.data)
let url = that.$route.query.next_url;
if (url){
that.$router.push({path: url})
}else {
that.$router.push({path: '/index'})
}
}else {
console.log(ret.data.error)
}
}).catch(function (ret) {
console.log('发生错误')
})
}
},
created(){
}
}
</script>
<style scoped>
</style>
同url不同标识的处理
页面组件的销毁和加载有这么一个特点,假设原url是/detail/1, 这时候在这个页面用router-link得到的/detail/2进行点击,发送浏览器地址栏发生改变,但是页面并没有重新加载,这时候可以使用绑定事件+this.$router.push({})方式解决
<script>
export default {
name: 'detail',
data () {
return {
detail:{
}
}
},
created(){
var nid = this.$route.params.id;
this.getDetail(nid);
},
methods:{
getDetail(nid){
var that = this;
this.$axios.request({
url:'http://127.0.0.1:8000/api/v1/course/' + nid + '/',
method: 'get'
}).then(function (ret) {
that.detail = ret.data.data;
}).catch(function (ret) {
console.log('error')
})
},
changeDetail(nid){
this.getDetail(nid);
this.$router.push({name: 'detail', params:{id:nid}})
}
}
}
</script>
切换保持active样式
<template>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li :class="{active: i == currentIndex}" v-for="(route,i) in routes" @click="changeActive(i)">
<router-link :to="route.url">{{ route.title }}</router-link>
</li>
</ul>
</div>
</div>
</nav>
</template>
<script>
export default {
name: 'Vheader',
data () {
return {
routes:[
{url:'/', title: '首页'},
{url:'/note', title: 'note'}
],
currentIndex:0
}
},
methods:{
changeActive(i){
this.currentIndex = i;
}
},
created(){
// console.log(this.$route)
for (var i=0;i<this.routes.length;i++){
if (this.routes[i].url === this.$route.path) {
this.currentIndex = i;
}
}
}
}
</script>
<style scoped>
</style>