Vue-Router(进阶)

256 阅读2分钟

使用全局守卫做登录操作

情景:当用户访问‘我的笔记’时 要对用户登录信息做判断 如果登录了 可以访问该页面 如果没登录 重定向到登录页面

1.在index的routes中写入对应的路由组件

    {
      path:'/notes',
      name:'notes',
      component:() => import('@/views/Notes')
    },
    {
      path:'/login',
      name:'login',
      component:() => import('@/views/Login')
    }

2.views中新建Login页面及Notes页面并简单编写

3.在main.js中 import下面写全局守卫router.beforeEach 该函数由((to,form,next) => {})组成

3.1验证to.path是否等于‘我的笔记’的路径'/notes'

3.2用localStorage.getItem('user')获取本地信息中的user的值

3.3如果有这个值 就放行 没有的话next('/login')到登录界面

//全局守卫
router.beforeEach((to, from, next) => {
  // console.log(to); 打印了当前路由信息
  // 用户访问了/notes
  if(to.path === '/notes'){
    //获取登录信息
    const user = JSON.parse(localStorage.getItem('user'));
    if(user){
      //用户已登录
      next();
    }else{
      //用户没有登录 跳转到登录界面
      next('/login');
    }
  }
  next();
})

4.编写Login视图

4.1写一个简单的登录界面

<template>
  <div>
    <h2>登录页面</h2>
    <input type="text" v-model='user'>
    <input type="password" v-model='pwd'>
    <button @click = 'handleLogin'>登录</button>
  </div>
</template>

4.2写入数据属性、获取用户信息、用localStorage.setItem()保存用户信息到本地、跳转到笔记页面

export default {
    data() {
      return {
        user: '',
        pwd:''
      }
    },
    methods: {
      handleLogin() {
        //1.获取用户名密码
        //2.与后端进行交互
        setTimeout(() => {
          let data = {
            user:this.user
          }
          //保存用户信息到本地
          localStorage.setItem('user',JSON.stringify(data.user));
          //跳转到笔记页面
          this.$router.push('/notes')
        }, 1000);
      }
    },
  }

组件内部守卫

组件内部有的内部守卫有三个

1.beforeRouterEnter(to,from,next){} (进入组件之前)

PS: 无法调用this 如果调用会显示undefined 但这个方法提供了一个回调函数可以取得实例

2.beforeRouterUpdate(to,from,next){} (组件重用的时候才起作用)

3.beforeRouterLeave(to,from,next){} (离开组件的时候起作用)

meta元信息实现权限控制

1. 在index中所需要实现权限控制的路由组件添加meta 并在里面添加一个自定义属性设置为true 这里是requireAuth

{
      path:'/blog',
      name:'blog',
      component:() => import('@/views/Blog'),
      meta:{
        //加入到需要验证的名单上(设置属性)
        requireAuth:true
      }
}

2.在main.js中设置全局守卫

2.1用to.matched.some方法判断是否有需要验证的条件(这里是判断是否存在requireAuth)

2.2如果有则判断是否有需要的验证信息 (这里判断是否有‘user’)

2.3如果没有 则用next方法跳转到登录页面 (这里可设置query中的redirect为现在的路径,为了登录后可直接跳转到现在的页面) 如果有登录信息则放行

router.beforeEach((to, from, next) => {
  //some方法里判断是否为true record为自定义的形参
  if(to.matched.some(record => record.meta.requireAuth)){
    //需要权限
    if(!localStorage.getItem('user')){
      next({
        path:'/login',
        //用来登录后直接跳转到刚刚需要登录才能打开的页面
        query:{
          redirect: to.fullPath
          //完整路径
        }
      });
    }else{
      next();
    }
  }
  next();
})

3.最后可在登录路由中登陆成功后跳转到刚刚的页面

        setTimeout(() => {
          let data = {
            user:this.user
          }
          //保存用户信息到本地
          localStorage.setItem('user',JSON.stringify(data.user));
          //跳转到笔记页面
          this.$router.push({
            path:this.$route.query.redirect
        })

路由组件内获取数据

有两个情况 一个是导航完成前获取数据 一个是导航完成后获取数据 导航完成后获取数据情况占大多数 这里讲解这个情况

1.在项目目录下添加新建一个vue.config.js

2.在里面配置模拟后端传输数据

module.exports = {
  devServer:{
    before:(app,serve) => {
      app.get('/api/post',(req,res) => {
        res.json({
          title:'Vue-Router的数据获取',
          body:'1.在导航完成之后获取数据'
        })  })
    }   }   }

3.关闭服务器 cnpm i axios -S 再重新启动服务器

4.main.js 引入 并且在Vue的原型链上添加

import axios from 'axios'
Vue.prototype.$http = axios;

5.index中引入post路由组件 并且新建一个Post视图

6.编写Post.vue

6.1在created时调用一个自定义方法
6.2在methods中 用async调用自定义方法
6.3创建数据
6.4编写页面
6.5用watch监听数据的获取
<template>
  <div class='post'>
    <div v-if='loading' class='loading'>
      Loading...
    </div>
    <div v-if='error' class='error'>{{error}}</div>
    <div v-if='post'>
      <h3>标题:{{post.title}}</h3>
      <h4>内容:{{post.body}}</h4>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        post: null,
        error:null,
        loading:false
      }
    },
    created () {
      console.log(this.$http);
      this.getPostData();
    },
    //监听数据的获取
    watch: {
      //当路由数据发生改变时请求相应的数据(假如后端传来的数据发生变化,重新返回该页面时,重新加载数据)
      $route:'getPostData'
    },
    methods: {
      async getPostData() {
        try {
          this.loading = true;
          const {data} = await this.$http.get('/api/post');
          this.loading = false;
          this.post = data;
        } catch (error) {
            this.error = error.toString();
        }
      }
    },
  }
</script>

<style lang="scss" scoped></style>