Vue-Router知识点总结

1.简介

SPA(Single Page Application)

  • Ajax前端渲染(前端渲染提高性能,但是不支持浏览器的前进后退操作) 
  • SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内 容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作 
  • SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历 史的变化、但是hash的变化不会触发新的URL请求
  • 在实现SPA过程中,最核心的技术点就是前端路由 

前端路由

  • 概念:根据不同的用户事件,显示不同的页面内容 
  • 本质:用户事件与事件处理函数之间的对应关系

2 路由组件传递参数

$route与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦 

第一种情况:

props的值为布尔类型

 const router = new VueRouter({ 
    routes: [       
        // 如果 props 被设置为 true,route.params 将会被设置为组件属性     
        { path: '/user/:id', component: User, props: true } 
    ] 
  }) 
 
  const User = { 
            props: ['id'], // 使用 props 接收路由参数     
                template: '<div>用户ID:{{ id }}</div>'  // 使用路由参数   
  } 

在定义路由规则的时候,为其添加了props属性,并将其值设置为true.那么在组件中就可以通过props:['id']的形式来获取对应的参数值。

3 路由守卫

Vue-router中的路由守卫,主要是对其内容进行保护,如果没有对应的权限,则不允许访问。

我们首先来看一下全局守卫,也就是所有的路由都会经过全局守卫来进行检测。

  //实现全局守卫
      router.beforeEach((to, from, next) => {
        //to:去哪个页面,from来自哪个页面,next继续执行.
        //判断哪个路由需要进行守卫,这里可以通过元数据方式
        if (to.meta.auth) {
          if (window.isLogin) {
            next();
          } else {
            next("/login?redirect=" + to.fullPath);
          }
        } else {
          next();
        }
      });

在上面的代码中,创建了路由守卫,但是需要判断的是需要对哪个路由进行守卫,这里就是通过元数据来进行判断的。如果所跳转到的路由有元数据,并且对应的auth属性为true表明是需要进行守卫的,那么下面就需要校验用户是否登录,这里是通过判断否window.isLogin的值是否为true来进行判断的(这里简化了操作,实际应用中应该存储到sessionStorage),如果条件成立则表明用户登录,就继续访问用户希望访问到的页面,否则跳转到登录页面,而且将用户希望访问的页面地址也传递到了登录页面,这样用户登录成功后,可以直接跳转到要访问的页面。

如果没有元数据,则继续访问用户要访问的页面。

4.addRoutes动态路由添加

在前面的案例中,我们都是将路由定义好,然后通过路由守卫来判断,某个用户是否登录,从而决定能否访问某个路由规则对应的组件内容。

但是,如果某些路由规则只能用户登录以后才能够访问,那么我们也可以不用提前定义好,而是在登录后,通过addRoutes方法为其动态的添加。

首先这里需要,还需要全局的路由守卫来进行校验判断,只不过这里全局路由守卫的逻辑发生了变化。

router.beforeEach((to, from, next) => {
        //to:去哪个页面,from来自哪个页面,next继续执行.
        if (window.isLogin) {
          //用户已经登录
          if (to.path === "/login") {
            // 用户已经登录了,但是又访问登录页面,这里直接跳转到用户列表页面
            next("/");
          } else {
            //用户已经登录,并且访问其它页面,则运行访问
            next();
          }
        } else {
          //用户没有登录,并且访问的就是登录页,则运行访问登录页
          if (to.path === "/login") {
            next();
          } else {
            //用户没有登录,访问其它页面,则跳转到登录页面。
            next("/login?redirect=" + to.fullPath);
          }
        }
      });

下面对登录组件进行修改

const Login = {
        data() {
          return {
            isLogin: window.isLogin,
          };
        },

        template: `<div>
            <button @click="login" v-if="!isLogin">登录</button>
            <button @click="logout" v-else>注销</button>
            </div>`,
        methods: {
          login() {
            window.isLogin = true;
            if (this.$route.query.redirect) {
              //动态添加路由:
              this.$router.addRoutes([
                {
                  path: "/",
                  component: App,
                  redirect: "/users",
                  children: [
                    {
                      path: "/users",
                      component: Users,
                      meta: {
                        auth: true,
                      },
                      // beforeEnter(to, from, next) {
                      //   if (window.isLogin) {
                      //     next();
                      //   } else {
                      //     next("/login?redirect=" + to.fullPath);
                      //   }
                      // },
                    },
                    { path: "/userinfo/:id", component: UserInfo, props: true },
                    { path: "/rights", component: Rights },
                    { path: "/goods", component: Goods },
                    { path: "/orders", component: Orders },
                    { path: "/settings", component: Settings },
                  ],
                },
              ]);
              this.$router.push(this.$route.query.redirect);
            } else {
              this.$router.push("/");
            }
          },
          logout() {
            this.isLogin = window.isLogin = false;
          },
        },
      };

在登录成功后,通过addRoutes方法动态的添加路由规则,也就是所添加的路由规则只能是在登录以后才能够访问,所以全局守卫的判断条件发生了变化,不在判断是否有元数据,而只是判断是否登录。如果登录了,想访问上面的路由规则,则运行访问,如果没有登录则不允许访问。

5. 路由组件缓存

利用keepalive做组件缓存,保留组件状态,提高执行效率。

<keep-alive include="home">
    <router-view></router-view>
</keep-alive>

使用include或者exclude时要给组件设置name(这个是组件的名称,组件的名称通过给组件添加name属性来进行设置)

当我们进行路由切换的时候,对应的组件会被重新创建,同时数据也会不断的重新加载。

如果数据没有变化,就没有必要每次都重新发送异步请求加载数据

应用场景

如果未使用keep-alive组件,则在页面回退时仍然会重新渲染页面,触发created钩子,使用体验不好。 在以下场景中使用keep-alive组件会显著提高用户体验,菜单存在多级关系,多见于列表页+详情页的场景如:

  • 商品列表页点击商品跳转到商品详情,返回后仍显示原有信息
  • 订单列表跳转到订单详情,返回,等等场景。

生命周期:  activateddeactivated会在keep-alive内所有嵌套的组件中触发  如:B页面是缓存页面    当A页面跳到B页面时,B页面的生命周期:activated(可在此时更新数据)    B页面跳出时,触发deactivated    B页面自身刷新时,会触发created-mouted-activated

6、Hash模式与History模式

        1 Hash模式与History模式区别

前端路由中,不管是什么实现模式,都是客户端的一种实现方式,也就是当路径发生变化的时候,是不会向服务器发送请求的。

如果需要向服务器发送请求,需要用到ajax方式。

两种模式的区别

首先是表现形式的区别

Hash模式

https://www.baidu.com/#/showlist?id=22256

hash模式中路径带有##后面的内容作为路由地址。可以通过问号携带参数。

当然这种模式相对来说比较丑,路径中带有与数据无关的符号,例如#?

History模式

https://www.baidu.com/showlist/22256

History模式是一个正常的路径的模式,如果要想实现这种模式,还需要服务端的相应支持。

下面再来看一下两者原理上的区别。

Hash模式是基于锚点,以及onhashchange事件。

通过锚点的值作为路由地址,当地址发生变化后触发onhashchange事件。

History模式是基于HTML5中的History API

也就是如下两个方法

history.pushState( )  IE10以后才支持

history.replaceState( )

7.Vue Router原理

Hash模式的工作原理。

  • ·URL#后面的内容作为路径地址,当地址改变的时候不会向服务器发送请求,但是会触发hashchange事件。
  • 监听hashchange事件,在该事件中记录当前的路由地址,然后根据路由地址找到对应组件。
  • 根据当前路由地址找到对应组件重新渲染。

History模式

  • 通过history.pushState()方法改变地址栏,并且将当前地址记录到浏览器的历史记录中。当前浏览器不会向服务器发送请求
  • 监听popstate事件,可以发现浏览器历史操作的变化,记录改变后的地址,单击前进或者是后退按钮的时候触发该事件
  • 根据当前路由地址找到对应组件重新渲染
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值