vue路由-3-监听-守卫-解决created只走一次的问题

1. 前言

1.路由确实在vue大型项目中听常用的,挺重要的,但是一般的小项目其实不用也没事
2.大家觉得难的 可能重点是路由守卫
3.那就试试自己能不能讲明白吧
4.当然还是建议大家看看 官网的路由守卫


2. 先从路由监听说起吧

2.1 首先路由系列的文章vue路由-2编程式导航存在通过路由切换的时候,created直走一次的问题,

2.2 解决方案 监听 -1

参数的名字 一般都叫to from或者 newV, oldV
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由

            watch:{
                   $route(to,from){
                    console.log(from.path);//从哪来
                    console.log(to.path);//到哪去
            //界面变化了就发请求
               }
            },

这种写法也有个问题,第一次的时候不走


2.3 解决方案 监听-2

immediate:true 设置 立刻监听,第一次切换也会走的

    watch:{
            $route:{
                immediate:true,
                 handler(newValue,oldValue){
                        console.log("详情页---newV:",newValue);
                         console.log("详情页---oldV:",oldValue);
                      }
               },
        },

3.导航守卫

3.1 官方定义

正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。


3.2 场景

路由守卫嘛 就是保护路由的 ,怎么保护呢
主要就是在进入路由之前进行拦截

一般都是 某些界面必须登录才能访问的时候做个守卫,比如
最近某些购物类网站,点击购物车相关操作话,如果你没有登录的话,会直接跳转到登录界面;
在以前是会正常跳到购物车界面,付账的时候在登录,登录后购物车信息是都在的


5. 全局守卫配置

5.1 标记需要进行守卫的路由

一般通过路由配置meta属性
路由文件

   {
    path: '/address',
    name: 'Address',
    component: () => import('../views/address.vue'),
    meta:{
       title: "标题",
       icon: "图标",
       needLogin:true
    }
  },

1.meta哈哈没想到这个时候正式元宇宙大火的概念
2.扯回整体, 这里的meta是一些原配置信息
3.needLogin 用来标记某个页面路由是否需要登录才能访问
4.title实际开发中,如果配置菜单 也可以配置标题
5.icon实际开发中,如果配置菜单 也可以配置菜单图标


5.2守卫逻辑

  1. 判断哪个路由需要守卫if(to.meta.needLogin)
  2. 不需要守卫的 直接 走else next()
  3. 需要守卫的进行第二步判断, 当前是否登录
    登录的时候发请求 请求成功 存放 一个auth或者token到本地localStorage
  4. 如果现在已经登录 直接 next()放行
    5.如果没登录 嘿嘿 此路是我开,此树是我栽,要想过,得听话,
    回去登录去

注意的是 这里跳转到登录界面,需要把拦截路由的地址传过去,
为啥传???
那还不是为了用户体验,为了顾客,为了逻辑闭环

比如用户从点击购物车界面 跳转到了登录界面,用户登录后,肯定要给界面重置到 购物车界面嘛,


5.3 具体守卫代码 方式-1

// 全局守卫
router.beforeEach((to,from,next)=>{
  // 判断路由是否需要守卫
  //meta数据的方式
  if(to.meta.needLogin){
    // 是否登录
    if(localStorage.token){
      next()
    }else{
      next("/login?redirect="+to.fullPath)
    }
  }else{
    //不需要守卫,直接放行
    next()
  }
})
export default router

5.4具体守卫代码 方式-2

router.beforeEach((to, from) => {
  if (to.meta.needLogin) {//说明当前路由需要登录之后才可进入
    if (!localStorage.token) {//还没登录 不为空 就行 简单的判断
      // return "/login?redirect=" + to.name; 
      return "/login?redirect=" + to.fullPath;
    }
  }
})

这个不用 next,但如果参数写了next 就必须用,不然不放行嘛,界面就一个也出不来
to.name 的方式 传的是 命名路由 跳转的时候也需要使用命名路由跳转

    this.$router.push({ name: this.$route.query.redirect});

to.fullPath 的方式 传的是 path路径
push也行,但是也可用 replace

    this.$router.replace(this.$route.query.to);

6. 登录后跳回去的配置

loginBtn() {
      this.isdisabled = true;
      setTimeout(() => {
        alert("登录成功");
        this.isdisabled = false;
        localStorage.token = "yzs假冒token";
        // 登录成功之后 回到被拦截的页面
       this.$router.replace(this.$route.query.redirect);
        }
      }, 3000);
    },
1.png
守卫的时候传参方式

1.可以传 通过query传递 path路径
2.也可以通过 params 传参
3.注意登录成功后 获取值的方式就行

        query:{redirect:"/two"} ,
        params: { toRouterName: to.name }})

命名路由的写法

      this.$router.push({ name: this.$route.params.toRouterName });

这样就形成了逻辑闭环 ,当然你还需退出或者注销的时候修改状态


7.单个路由守卫

全局守卫,肯定是每个路由跳转都要进行判断的,也就是each遍历,这里面的效率问题就需要考虑
所以,如果只是极个别的路由需要判断,那就单独守卫
比如保护整村的人,和保护一个人那是完全不一样的

注意和全局的不同

  1. 钩子不一样了,这个是Enter进到这个路由了,判断
    2.因为已经进到这个路由了,自然也不需要在判断哪个路由需要守卫了
  2. 直接判断登录状态就行
  {
    path: '/cart',
    name: 'Cart',
    component: () => import("@/views/cart.vue"),
    meta: {
      title: "标题",
      icon: "图标",
      needLogin: true
    },
    //************* */ 单个的路由守卫
    beforeEnter(to, from, next) {
      //  判断当前是否登录
      if (localStorage.token) {
        next()
      } else {
        next({ name: "Three",
        query:{to:"/cart"} ,
        params: { toRouterName: to.name },})
      }
    }
  },

8. 组件级守卫

1.和 methds 是同级的
2.beforeRouteEnter 和 单独的守卫beforeEnter写法是不一样的
3.这个是存储 localStorage的逻辑
4.login页和单个守卫用的是一样的

 beforeRouteEnter(to, from, next) {
    // 当前是否登录
    if (localStorage.token) {
      next();
    } else {
      next({ name: "Login", params: { toRouterName: to.name } });
    }
  },

9. 组件级守卫 钩子详解

const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

1. 注意 Enter钩子不能访问 this

因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

注意

beforeRouteEnter 是支持给next传递回调的唯一守卫。对于 beforeRouteUpdatebeforeRouteLeave来说,this已经可用了,所以不支持传递回调,因为没有必要了。


10.完整的导航解析流程

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


11. 想学习更多的实战配置 可以去看下各大开源的项目源码

比如各大框架的admin模板


参考资料

路由守卫


初心

我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理;
如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
共勉

你可能感兴趣的:(vue路由-3-监听-守卫-解决created只走一次的问题)