vue-router 常用知识点二

目录

- 1.vue-router 动态路由匹配

- 2.router-link组件及其属性

- 3.vue-router路由的两种模式

- 4.vue-router有哪几种导航钩子( 导航守卫 )?

- 5.完整的导航解析流程

- 6.vue-router实现路由懒加载( 动态加载路由 )参考https://www.jianshu.com/p/a88a2ae4ebde


- 1. vue-router 动态路由匹配

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:

const User = {
  template: '
User
' } const router = new VueRouter({ routes: [ // 动态路径参数 以冒号开头 { path: '/user/:id', component: User } ] })

现在呢,像 /user/foo/user/bar 都将映射到相同的路由。

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:

const User = {
  template: '
User {{ $route.params.id }}
' }

你可以看看这个在线例子。

你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:

模式 匹配路径 $route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: '123' }

除了 $route.params 外,$route 对象还提供了其它有用的信息,例如,$route.query (如果 URL 中有查询参数)、$route.hash 等等。你可以查看 API 文档 的详细说明。

- 2. router-link组件及其属性

支持用户在具有路由功能的应用中 (点击) 导航 通过 to 属性指定目标地址
一:router-link组件的props:

  • to

表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push()

Home
渲染结果:
Home
router
渲染结果:
router
  • tag:

指定组件最终被渲染成什么标签;非必须;如果没有tag属性,router-link最终会被渲染成a标签。在上面的栗子中,渲染成了li标签。

Home
渲染结果:
  • Home
  • 此时依旧会监听点击事件,触发导航
    • replace:

    当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。

    
    
    • append:

    则在当前 (相对) 路径前添加基路径。/a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

    
    
    • active-class:

    • 表示激活这个链接时,添加的class,默认是router-link-class。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
    • exact:

    "是否激活" 默认类名的依据是 inclusive match (全包含匹配)。

    
    
    
    • event:

    默认值: 'click' 声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。

    • exact-active-class:

    默认值: "router-link-exact-active" 配置当链接被精确匹配的时候应该激活的 class。

    - 3.vue-router路由的两种模式mode

    • 类型: string

    • 默认值: "hash" (浏览器环境) | "abstract" (Node.js 环境)

    • 可选值: "hash" | "history" | "abstract"

      配置路由模式:

      • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。

      • history: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。

      • abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式

    • hash模式:

    url 的 hash 是以 # 开头,原本是用来作为锚点,从而定位到页面的特定区域。当 hash 改变时,页面不会因此刷新,浏览器也不会向服务器发送请求。
    http://www.xxx.com/#/home
    同时, hash 改变时,并会触发相应的 hashchange 事件。所以,hash 很适合被用来做前端路由。当 hash 路由发生了跳转,便会触发 hashchange 回调,回调里可以实现页面更新的操作,从而达到跳转页面的效果。
    hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。

      window.onhashchange = function(event){
        console.log(event);
      }
    
    
    vue-router 常用知识点二_第1张图片
    image

    可以看到里边有两个属性newURL和oldURL。可以通过模拟改变hsh的值,动态页面数据。

    vue-router 常用知识点二_第2张图片
    image

    尽管浏览器没有请求 服务器,但是页面状态和url已经关联起来了,这就是所谓的前端路由,单页应用的标配。

    • history模式:

    HTML5 规范中提供了 history.pushState 和 history.replaceState 来进行路由控制。通过这两个方法,可以实现改变 url 且不向服务器发送请求。同时不会像 hash 有一个 # ,更加的美观。但是 History 路由需要服务器的支持,并且需将所有的路由重定向到根页面。

    History 路由的改变不会去触发某个事件,所以我们需要去考虑如何触发路由更新后的回调。

    有以下两种方式会改变 url:

    • 调用 history.pushState 或 history.replaceState;
    • 点击浏览器的前进与后退。

    第一个方式可以封装一个方法,在调用 pushState(replaceState)后再调用回调。

    function push (url) {
     window.history.pushState({}, null, url);
     handleHref();
    }
     
    function handleHref () {
     console.log('render');
    }
    

    第二个方式,浏览器的前进与后退会触发 popstate 事件。

    window.addEventListener('popstate', handleHref);
    
    vue-router 常用知识点二_第3张图片
    image

    前进,后退,跳转操作方法:

      history.go(-3);//后退3次
      history.go(2);//前进2次
      history.go(0);//刷新当前页面
      history.back(); //后退
      history.forward(); //前进
    
    

    https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90

    这篇文章介绍的较为详细,讲到了实现原理https://juejin.im/post/5b330142e51d4558b10a9cc5

    - 4.vue-router有哪几种导航钩子( 导航守卫 )?

    vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
    例如判断登录信息:没登录全部跳到登录页。判断必要操作是否进行没进行的话中断跳转。
    参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

    分为三大类:全局守卫、路由守卫、组件守卫

    [#]全局前置守卫

    你可以使用 router.beforeEach 注册一个全局前置守卫:

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

    当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
    每个守卫方法接收三个参数:

    • to: Route: 即将要进入的目标 路由对象

    • from: Route: 当前导航正要离开的路由

    • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

      • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

      • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

      • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: truename: 'home' 之类的选项以及任何用在 router-linkto prop 或 router.push 中的选项。

      • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

    确保要调用 next 方法,否则钩子就不会被 resolved。

    #全局解析守卫

    在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

    #全局后置钩子

    你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

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

    #路由独享的守卫

    你可以在路由配置上直接定义 beforeEnter 守卫:

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

    这些守卫与全局前置守卫的方法参数是一样的。

    #组件内的守卫

    最后,你可以在路由组件内直接定义以下路由导航守卫:

    • beforeRouteEnter
    • beforeRouteUpdate (2.2 新增)
    • beforeRouteLeave
    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`
      }
    }
    
    

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

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

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

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

    beforeRouteUpdate (to, from, next) {
      // just use `this`
      this.name = to.params.name
      next()
    }
    
    

    这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

    beforeRouteLeave (to, from , next) {
      const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
      if (answer) {
        next()
      } else {
        next(false)
      }
    }
    

    #完整的导航解析流程

    1. 导航被触发。
    2. 在失活的组件里调用离开守卫。
    3. 调用全局的 beforeEach 守卫。
    4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
    5. 在路由配置里调用 beforeEnter
    6. 解析异步路由组件。
    7. 在被激活的组件里调用 beforeRouteEnter
    8. 调用全局的 beforeResolve 守卫 (2.5+)。
    9. 导航被确认。
    10. 调用全局的 afterEach 钩子。
    11. 触发 DOM 更新。
    12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
    vue-router 常用知识点二_第4张图片
    图片描述

    你可能感兴趣的:(vue-router 常用知识点二)