Vue-Router的使用总结(含路由懒加载及守卫)

1,457 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

1. 路由的基本结构

在使用路由的时候,通常通过两个js文件来编写,其中index.js文件用于编写路由的配置信息(重写、守卫等),而routes.js文件则是用于将各个组件注册为路由

还需要在入口main.js文件中进行注册路由

//对上面的router进行引入
import router from '@/router'

new Vue({
  render: h => h(App),
  //注册路由
  router,
}).$mount('#app')

在main.js中注册了路由之后,项目中的所有组件身上将会有$router、$route属性

$router一般用于进行路由跳转:push、replace、back、forward、go

$route一般读取当前路由的一些参数属性:path、name、query、params、meta

2. 路由push和replace的重写

  • 如果直接使用Vue自带的push和replace方法,当多次点击同一个路由时,控制台就会报错,虽然不会影响代码的功能实现,但是也需要解决,于是需要对push和replace方法进行重写
//先将VueRouter的push保存一份
let originPush = VueRouter.prototype.push
let originReplace = VueRouter.prototype.replace
//重写push|replace
//第一个参数:告诉原来push方法,往哪里跳转(传递哪些参数)
//第二个参数:成功回调
//第三个参数:失败回调
VueRouter.prototype.push = function (location, resolve, reject) {
    if (resolve && reject) {
        //call||apply区别
        //相同点:都可以调用函数一次,都可以篡改函数上下文一次
        //不同点:call与apply传递参数:call传递参数用逗号隔开,apply方法执行,传递数组
        originPush.call(this, location, resolve, reject)
    } else {
        originPush.call(this, location, () => { }, () => { })
    }
}
VueRouter.prototype.replace = function (location, resolve, reject) {
    if (resolve && reject) {
        originReplace.call(this, location, resolve, reject)
    } else {
        originReplace.call(this, location, () => { }, () => { })
    }
}
//配置路由
let router = new VueRouter({
    //配置路由
    routes,
    //滚动行为
    scrollBehavior(to, from, savedPosition) {
        //返回的这个y=0代表的是滚动条在最上方
        return { y: 0 }
    }
})
  • 重写过后,路由的跳转还是正常使用,没有什么较大的变化

3. 将组件注册为路由

1. 普通方式注册路由

//引入路由组件
import Home from '@/pages/Home'
import Center from '@/pages/Center'
import Msg from '@/pages/Msg'

export default[
  {
    path:'*',
    //默认路由重定向
    redirect:'/home'
  },
  {
    path:'/home',
    component:Home,
    meta: { show: true },
    //二级路由
    children:[
      {
        path:'/center',
        component:Center
      },
    ]
  },  
  {
    path:'/msg',
    //在调用$router.push方法时,传入的参数可以是path也可以是name来指定跳转的路由
    name:'msg',
    component:Msg,
    //路由元信息
    meta: { show: true }
  },
]
  • path

指定路由对应的跳转路径,一般都是小写,并且与组件名保持一致

如果是'*'或'/'即为默认路由地址(第一次访问该网站),一般需要重定向到首页

  • name

利用name属性可以给路由命名,在调用$router.push方法或者route-link中跳转时,传入的参数可以是path也可以是name来指定跳转的路由

  • component

将组件和路由绑定注册

  • children

注册二级路由

  • meta

路由元信息,进行路由跳转的时候可以通过meta对象中所带的属性来判断当前路由是否需要进一步处理

  • redirect

重定向路由,当跳转到该路由时自动重定向到其他路由(一般用于跳转默认路由)

2. 路由懒加载

  • 路由懒加载即当路由被访问时才加载对应的组件,所以在routes.js文件中无需引入组件
export default[
  {
    path: '*',
    redirect: '/home'
  },
  {
    path:'/home',
    component:() => import('@/pages/Home'),
    meta: { show: true },
    children:[
      {
        path:'/center',
        component:() => import('@/pages/Home/Center')
      },
    ]
  },
  {
    path:'/msg',
    name:'msg',
    component:() => import('@/pages/Msg'),
    meta: { show: true }
  },
]

4. 路由跳转

  • 首先需要在页面结构设置一个路由组件的出口,即路由组件展示的位置
<router-view></router-view>

1. 声明式导航

  1. 直接通过路由地址跳转
<router-link to="/home">home</router-link>
  1. 使用对象中带path的方式跳转
<router-link :to="{path:'/home',query:{a:10}}">home</router-link>
  1. 使用对象中带name的方式跳转
<router-link :to="{name:'home',params:{b:20}}">home</router-link>

采用对象写法还可以携带query或params参数

2. 编程式导航

  1. 字符串
router.push('/home')
  1. 使用对象中带path的方式跳转
router.push({
  path:"/home",
  query:{
    a:10
  }
})
  1. 使用对象中带name的方式跳转
router.push({
  name:"home",
  params:{
    b:20
  }
});

5. 路由参数

在跳转路由时传递参数,可以在配置对象中添加queryparams参数属性

路由可以传递参数,那便肯定可以在目标路由对其进行读取

在路由内部如果希望访问到路由携带的参数,可以直接访问$route对象上的参数属性

$route上常用的属性包括:path、name、params、query、meta

6. 导航守卫

  • 一般用于阻止某个状态的用户前往指定的页面

例如:已登录状态的用户无法前往登录页面

  • 守卫分为全局守卫、路由独享守卫和组件内守卫

1. 全局守卫

  • 全局守卫有全局前置守卫、全局解析守卫和全局后置守卫
  • 最常用的是全局前置守卫,会在路由跳转之前进行判断
router.beforeEach(to,from,next){
  //to:可以获取你要跳转到哪个路由的信息
  //from:可以获取到你从哪个路由而来的信息
  //next:放行函数    next()放行  next(path)放行到指定路由    next(false)
  ......
}

2. 路由独享守卫

{
    path: '/trade',
    component: () => import('@/pages/Trade'),
    meta: { show: true },
    //路由独享守卫
    beforeEnter: (to, from, next) => {
        //去交易页面,必须是从购物车而来
        if (from.path == '/shopcart') {
            next()
        } else {
            //其他的路由组件而来,则停留在当前
            next(false)
        }
    }
},

3. 组件内守卫

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