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>
posted @ 2018-07-26 16:24  龙云飞谷  阅读(565)  评论(0编辑  收藏  举报