浅谈vue-router及总结

1、动态路由匹配

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

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

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

this.$route.params.id

2、响应路由参数的变化

提醒一下,当使用路由参数时,例如从/user/foo导航到/user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

复用组件时,想对路由参数的变化作出响应的话,你可以简单的watch(检测变化)$route对象:

 watch: {
    '$route' (to, from) {
      // 对路由变化作出响应...
        console.log(to,from)
    }
  }

3、嵌套路由

借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系。

<div id="app">
  <router-view></router-view>
</div>

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

这里的 <router-view> 是最顶层的出口,渲染最高级路由匹配到的组件。同样地,一个被渲染组件同样可以包含自己的嵌套 <router-view>。例如,在 User 组件的模板添加一个 <router-view>

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}

要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 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
        }
      ]
    }
  ]
})

要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

你会发现,children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。

此时,基于上面的配置,当你访问 /user/foo 时,User 的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。如果你想要渲染点什么,可以提供一个 空的 子路由:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id', component: User,
      children: [
        // 当 /user/:id 匹配成功,
        // UserHome 会被渲染在 User 的 <router-view> 中
        { path: '', component: UserHome },

        // ...其他子路由
      ]
    }
  ]
})

4、跳转路由,官方叫编程式导航,其实就是跳转路由,及获取参数  

router.push()

以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

/ 字符串
router.push('home')

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

// 路由是这样的  /user/:id
// 命名的路由  变成 /user/123
router.push({ name: 'user', params: { userId: 123 }})
router.push({ path: '/user/3' })
对应的获取参数:this.$route.params.id

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

//既有动态路由又有查询参数
router.push({path:'/user/3',query:{plan:'c'}})


const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123

**这里的 params 不生效**
router.push({ path: '/user', params: { userId }}) // -> /user

下面举个项目经常遇见的例子:

第一种($route获取参数)经常用

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


要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>


这跟代码调用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 }})


获取参数:
this.$route.params.id

第二种(props获取参数

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User,
      props: true 
    }
  ]
})


方法很多,熟练使用一种就行

router.replace()

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

router.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

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

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

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

5、导航守卫

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

// 路由守卫
router.beforeEach((to, from, next) => {
  // 数据的校验
  /* 
    if(to.fullPath === '/login'){
      next()
    }else{
      next('/login);
      // 可以和router里面一样
      next({
        path:'/login',
      })
    }
  */
  console.log('to', to);
  console.log('from', from);
  next()
})

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

router.beforeResolve((to, from, next) => {
  console.log('to', to);
  console.log('from', from);
  next()
})

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

router.afterEach((to, from) => {
  console.log('to', to);
  console.log('from', from);
})

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

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

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

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

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
   //获取数据  加载数据
    next(vm => {
      console.log(vm, vm.msg);//在这是拿不到this vm可以 注意
    });
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
    next();
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
    // 切换页面的时候 =》 提醒是否保存已编辑内容
    next();
  }
}

完整的导航解析流程:

  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 的回调函数。

猜你喜欢

转载自blog.csdn.net/lbPro0412/article/details/81705728