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

Vue Router - 详细总结

程序员文章站 2022-03-21 19:26:24
路由的配置Vue 的特点是数据驱动和组件化,根据组件化的特点,我们可以很方便的用 Vue 来实现单页面应用程序。在 Vue.js 中,我们已经可以通过组件名来切换组件,但是这样做浏览器的地址栏内容不会发生变化,为了解决这一问题,我们可以引入 Vue Router 通过路由来标识组件,并且把路由带入到地址栏中。这里我们通常使用 hash (#) 形式来约定路由,因为 HTTP 请求中不会包含 hash (#) 相关的内容,所以单页面程序中的页面跳转主要用 hash (#) 实现。绑定路由(基础)首先我们...

路由的配置

Vue 的特点是数据驱动组件化,根据组件化的特点,我们可以很方便的用 Vue 来实现单页面应用程序。在 Vue.js 中,我们已经可以通过组件名来切换组件,但是这样做浏览器的地址栏内容不会发生变化,为了解决这一问题,我们可以引入 Vue Router 通过路由来标识组件,并且把路由带入到地址栏中。这里我们通常使用 hash (#) 形式来约定路由,因为 HTTP 请求中不会包含 hash (#) 相关的内容,所以单页面程序中的页面跳转主要用 hash (#) 实现。

绑定路由

基础绑定

首先我们要进行路由与组件的绑定,绑定之后要把整个路由实例挂载到全局 Vue 实例上,这里我们举一个简单的例子:

// 1. 定义组件
// 在项目开发中,通常会使用 import 的方式引入
const componentA = { template: '<div> 组件A </div>' }
const componentB = { template: '<div> 组件B </div>' }

// 2. 定义路由,数组格式
const routes = [
	{ path: '/componentA', component: componentA },
	{ path: '/componentB', component: componentB }
]

// 3. 创建路由实例
let router = new VueRouter({
	routes: routes
})

// 4. 将路由实例挂载到全局 Vue 实例中
new Vue({
	router,
    render: h => h(App)
}).$mount('#app')
动态路由匹配

router 路由传参有两种方式,一种是将参数以 ?key=value&key=value 的形式拼接到路由后面,另一种是将参数拼合到路由中,例如:/user/123 ,其中 123 是参数,这种传参方式需要在路由配置的时候声明参数的 key 值,作为路径参数

const routes = [
	{ path: '/componentA/:id', component: componentA },
	{ path: '/componentB/:id', component: componentB }
]

一个路径参数使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。$route 用来存放路由中的相关信息。

注意,当使用路由参数时,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。如果有需要,可以利用 catch 监听。

命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。可以在创建实例的时候,在 routes 配置中给某个路由设置名称。

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})
嵌套路由

router-view 是路由出口,路由匹配到的组件将渲染在这里。同样地,一个被渲染组件同样可以包含自己的嵌套 router-view。要在嵌套的出口中渲染组件,需要在父级路由的参数中使用 children 配置:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /user/:id/posts 匹配成功
          // UserPosts 会被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})
重定向

重定向也是通过 routes 配置来完成:

// 从 /a 重定向到 /b
const router1 = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})

// 重定向到命名路由
const router2 = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

经过一顿操作,现在我们已经可以在项目中使用路由了。

路由的基本使用

在项目中,我们经常会遇到两种情况来使用路由进行跳转页面。第一种是操作页面元素后,子页面进行跳转;第二种是在 JS 中操作页面的跳转。这两种需求引出了路由的两种使用方式:声明式导航编程式导航

声明式导航其实是 Vue 已经把编程式导航封装成了一个组件来给我们使用:router-link ,将要跳转的路由当做 to 属性的值传入,所以说,点击 <router-link :to=" xxx "></router-link> 等同于编程式导航$router.push()

编程式导航:在 Vue 实例中,可以通过 $router 访问路由实例,其中提供了几个方法方便我们操作路由:

  1. push :是我们最常用的方法,可以接收一个字符串或者设置对象作为参数
// 字符串
this.$router.push('home')

// 对象
this.$router.push({ path: 'home' })

// 命名的路由
this.$router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})

注意:pathparams 同时存在时,params 失效,取而代之的是将 params 直接拼入 path

this.$router.push({ path: '/register', params: { userId: '123' }}) // params 失效
// 应使用
const userId = '123'
this.$router.push({ path: '/register/${userId}' }) // --> /register/123
  1. go$router.go() 等同于 history.go()
// 在浏览器记录中前进一步,等同于 history.forward()
this.$router.go(1)

// 后退一步记录,等同于 history.back()
this.$router.go(-1)

// 前进 3 步记录
this.$router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
this.$router.go(-100)
this.$router.go(100)
路由守卫

路由守卫是路由在切换过程中一系列钩子函数的统称,每个守卫方法接收三个参数:

  1. to :Route 实例,即将要进入的目标路由对象

  2. from :Route 实例,即将要离开的目标路由对象

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

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

    b. next(false) :中断跳转

    c. next('/') :跳转到指定路由

全局路由守卫

router.beforeEach :全局前置守卫

router.beforeResolve :全局解析守卫,和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

router.afterEach :全局后置钩子,不会接收 next 函数

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

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

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

router.afterEach((to, from) => {
  // ...
})
组件内的守卫
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`
  }
}
路由独享的守卫
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
完整的导航解析流程
  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

本文地址:https://blog.csdn.net/qq_40311523/article/details/107248894

相关标签: Vue