欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆

程序员文章站 2022-04-30 13:38:23
...


(七)中学了vue-route的基本使用,当然vue-route的功能不止于此,在这里我结合vue-route的导航守卫和route对象中的meta对象,来提供一个跳转时强行转入登陆页面的功能。

一、导航守卫简介

正如其名,vue-router 提供的导航守卫主要用来通过跳转取消的方式守卫导航(对锚点的改变非常敏感)。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。参数或查询的改变并不会触发进入/离开的导航守卫。简单来说,就是对每个路由的变化,我们定义的一系列动作。

1-全局前置守卫:

以下代码可以创建一个前置守卫,我们先创建一个VueRouter对象,然后通过实例化的VueRouter对象创建一个前置守卫。

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

参数:
每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: !一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

2-路由独享的守卫

直接在router实例化对象的routes列表中,在每个路由的后面进行定义

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

3-路由守卫的调用时机

  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被**的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

4-tips

一定一定一定要调用next函数,不然就卡住了。

5-示例

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆

二、meta+导航守卫实现权限控制

我们使用三个页面,一个按钮来简单实现页面强制登陆登陆的功能。前端的逻辑大概是这样的:我们在首页显示:首页-博客两个按钮,点击首页显示”这里是首页“字样,点击博客强制跳转到登陆页面(如果没有登陆的话),登陆之后跳转到博客页面,此时显示退出按钮,退出后返回首页,再次进入博客需要重新进行登陆。

1-HTML元素定义

这是首页要显示的内容,这个button我们只有登陆了才会进行显示,因此使用v-show和一个变量连接起来,方便我们进行控制。

   <div id="app">
     <router-link to="/home">首页</router-link>
     <router-link to="/blog">博客</router-link>
     <button @click="exitHandler" v-show='isShow'>退出</button>
     <router-view></router-view>
   </div>

2-组件元素定义

我们有三个组件,分别是首页/博客/登陆页,比较复杂的是登陆页(先看代码,下文解释)

   var Home={
     template:`
      <div>这里是首页</div>
     `
   };
   var Blog={
     template:`
      <div>这里是博客</div>
     `
   };
   var Login={
     data(){
       return{
         name:"yfZhang",
         password:"123456"
       }
     },
     template:`
      <div>
            <input type='text' v-model='name'/>
            <input type="text" v-model='password'/>
            <input type="button" value='登陆' 
            @click="loginHandle()"/>
        </div>
     `,
     methods:{
      loginHandle(){
        //登陆
        vm.isShow = true;
        localStorage.setItem("user", {name:this.name, 
          pwd:this.password});
        //跳转到博客页面:编程式导航
        this.$router.push({
          name:"blog"
        })
      }
     }
   };

登陆页的组件其实就是维护了两个参数,两个文本框和一个button,然后绑定一个点击事件,每次点击登陆,我们将用户名与密码本地存储,然后使用编程式导航的方式进行页面跳转。这是导航的一种方式(使用this.$router.push({name : ''})name对应的value是我们的其中一个路由的名字,该语句直接跳转到name路由对应的地址)

3-router对象的定义-meta属性的添加

在创建router对象的时候,我们可以给一个router对象添加meta属性,用作未来的访问控制。也就是说每当我们跳转到对应的页面时,我们查询meta中的auth参数,如果他的值时true,那么我们直接跳转到登陆页面,而不是博客页面。

    //创建router对象
    var router = new VueRouter({
      routes:[
        {
          path:"/home",
          component: Home
        },
        {
          path:"/blog",
          name:"blog",
          component:Blog,
          //给未来的路由做权限控制
          meta:{
            //证明 用户访问该组件的时候需要登陆
            auth:true
          }
        },
        {
          path:"/login",
          component:Login
        }
      ]
    });

4-全局守卫实时监听

每次地址跳转的时候吗我们的全局守卫就会运行,我们先打印来源和目的地址,然后判断转向的页面是否要求必须登陆(metaauth对象的值为true即必须登陆),多次点击博客我们会以本地存储是否有用户名密码为标准,有的话就是已经登陆过的,否则就转向登陆页面。当然如果去向页面根本没有这个要求,我们当然直接放行,next函数啥都不做。

    router.beforeEach((to, from, next)=>{
      console.log(to);
      console.log(from);
      if(to.meta.auth){
        //用户点击了博客链接,需要登陆
        if(localStorage.getItem('user')){
          //本地存储不是空的,已经登陆了。
          next();
        }else{
        next({
            //
            path:"/login"
          })
        }
      }else{
        //false直接放行,如果不调用可能会卡住页面
        next();
      }
      next();
    });

5-Vue实例对象掌控全局

Vue对象是不可缺少的一环,这里控制着退出键什么时候显示的参数isShow,以及对退出按钮做出的相应。

    vm = new Vue({
      el:"#app",
      data(){
        return{
          isShow: false
        }
      },
      //交给Vue实例化对象管理
      router,
      methods:{
        exitHandler(){
          localStorage.removeItem('user');
          vm.isShow=false;
          this.$router.push({
            name:"home"
          })
        }
      }
    })

6-完整代码

注意包的路径可能不太一杨

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <title>myVue</title>
    <!--由于vue-router是依赖于vue的,所以两个包必须都引入,而且顺序必须是这样-->
    <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
  </head>
 <body>
   <div id="app">
     <router-link to="/home">首页</router-link>
     <router-link to="/blog">博客</router-link>
     <button @click="exitHandler" v-show='isShow'>退出</button>
     <router-view></router-view>
   </div>
   <script type="text/javascript">
   var Home={
     template:`
      <div>这里是首页</div>
     `
   };
   var Blog={
     template:`
      <div>这里是博客</div>
     `
   };
   var Login={
     data(){
       return{
         name:"yfZhang",
         password:"123456"
       }
     },
     template:`
      <div>
            <input type='text' v-model='name'/>
            <input type="text" v-model='password'/>
            <input type="button" value='登陆' 
            @click="loginHandle()"/>
        </div>
     `,
     methods:{
      loginHandle(){
        //登陆
        vm.isShow = true;
        localStorage.setItem("user", {name:this.name, 
          pwd:this.password});
        //跳转到博客页面:编程式导航
        this.$router.push({
          name:"blog"
        })
      }
     }
   };
    //创建router对象
    var router = new VueRouter({
      routes:[
        {
          path:"/home",
          name:"home",
          component: Home
        },
        {
          path:"/blog",
          name:"blog",
          component:Blog,
          //给未来的路由做权限控制
          meta:{
            //证明 用户访问该组件的时候需要登陆
            auth:true
          }
        },
        {
          path:"/login",
          component:Login
        }
      ]
    });
    router.beforeEach((to, from, next)=>{
      console.log(to);
      console.log(from);
      if(to.meta.auth){
        //用户点击了博客链接,需要登陆
        if(localStorage.getItem('user')){
          //本地存储不是空的,已经登陆了。
          next();
        }else{
        next({
            //
            path:"/login"
          })
        }
      }else{
        //false直接放行,如果不调用可能会卡住页面
        next();
      }
      next();
    });
    vm = new Vue({
      el:"#app",
      data(){
        return{
          isShow: false
        }
      },
      //交给Vue实例化对象管理
      router,
      methods:{
        exitHandler(){
          localStorage.removeItem('user');
          vm.isShow=false;
          this.$router.push({
            name:"home"
          })
        }
      }
    })
  </script>
 </body>

</html>

三、运行实例

1-开始页面

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆

2-首页

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆

3-博客页

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆

4-登陆自动跳转

vue项目实战(九):meta+导航守卫-权限控制:实现页面强制登陆
在这里你可以多次尝试首页/博客的转换,登陆状态不会改变。退出后返回首页,再点击博客就需要重新登陆了。

相关标签: 开发