vue-router 路由

安装及引入

// 安装
npm i vue-router
// 引入 main.js
...
import VueRouter from "vue-router"
import router from './router'
... Vue.use(VueRouter) ...
new Vue({ router, // Vue 实例上创建 render: h => h(App), }).$mount('#app')

 配置路由

编写路由配置项

   路由配置文件通常创建在 src/router/index.js

// src/router/index.js
//
引入VueRouter import VueRouter from 'vue-router' // 引入路由组件 import About from '../components/About' import Home from '../components/Home' // 创建router实例对象,去管理一组一组的路由规则 const router = new VueRouter({ routes:[ { path:'/about', component:About }, { path:'/home', component:Home } ] }) // 暴露router export default router

实现路由切换

   在切换处(如导航栏)配置 router-link 组件, 并通过 router-view 指定展示位置

  activate-class 表示激活时添加的class

<router-link active-class="active" to="/about">About</router-link>
<router-view></router-view>

  注:1.路由组件通常存放在 pages 文件夹,一般组件通常存放在 components 文件夹

    2.通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。(可使用 keep-alive 组件缓存路由)

    3.整个 Vue 实例只能有一个 router ,可以通过组件的 $router 属性获取到

命名路由

  当路由层级过多时,可以使用命名的方式来简化路径配置,如下:

{
   path:'/demo',
   component:Demo,
   children:[
      {
         path:'test',
         component:Test,
         children:[
            {
               name:'hello', //给路由命名
               path:'welcome',
               component:Hello,
            }
         ]
      }
   ]
}

  简化跳转:

// 简化前,需要写完整的路径
<router-link to="/demo/test/welcome">跳转</router-link>

// 简化后,直接通过名字跳转
<router-link :to="{name:'hello'}">跳转</router-link>

// 简化写法配合传递参数
<router-link 
   :to="{
      name:'hello',
      query:{
         id:666,
         title:'你好'
      }
   }"
>跳转</router-link>

多级路由

  路由中可嵌套路由,实现多级路由配置,通过 children 配置项,配置子路由。

   routes:[
       {
           path:'/about',
           component:About,
       },
       {
           path:'/home',
           component:Home,
           children:[ //通过children配置子级路由
               {
                   path:'news', //此处一定不要写:/news
                   component:News
               },
               {
                   path:'message',//此处一定不要写:/message
                   component:Message
               }
           ]
       }
   ]

  路由跳转时,要写完整路径

<router-link to="/home/news">News</router-link>

接收参数

  路由切换时,可以向组件内传递参数,以下是几种传参方式

query参数

// 写法一
<router-link :to="/home/message/detail?id=666&title=你好">

// 写法2
<router-link 
   :to="{
      path:'/home/message/detail',
      query:{
         id:666,
         title:'你好'
      }
   }"
>跳转</router-link>

  获取参数:

this.$route.query.id
this.$route.query.title

params参数

  声明参数:

{
   name:'home',    
   path:'/home/:id/:title', //使用占位符声明接收params参数
   component:Home,
}

  配置参数:

// 写法1
<router-link :to="/home/666/你好">跳转</router-link>

// 写法2
<router-link 
   :to="{
      // 注意,使用此种写法,必须用name配置路由
      name:'home',    
      params:{
         id:666,
         title:'你好'
      }
   }"
>跳转</router-link>

  接收参数:

this.$route.params.id
this.$route.params.title

props参数

  路由还可通过配置项中的 props 属性传值,由组件的 props 接收

  分为三种写法:

  1.直接传值(不灵活)

{
    path:"/home",
    component: Home,
    props:{ id: 666, title: '你好'}
}

  组件中的 props 配置:

props:[ "id", "title" ]

  2.配合 params 参数,此时配置项中的 props 为一个 boolean  值,会把接收到的所有的params参数传递给组件中的props。

{
    path:"/home",
    component: Home,
    props: true
}

  3.配合 query 参数,通过函数返回值的形式,传入 query 参数,配合组件中的 props 接收

props({query}){
    return{
        id: query.id,
        title: query.title,
    }
}

  解构的对象参数打印在控制台如下:

replace

  浏览器的历史记录有两种写入方式:分别为 push 和 replace ,push 是追加历史记录,replace 是替换当前记录。路由跳转时候默认为 push
  开启 replace 模式:
<router-link replace .......>News</router-link>

动态路由

有的时候,我们需要把满足某种规则的路由全部匹配到同一个组件,我们不可能为每一个符合规则的路径都进行配置

...
{
  path: '/home/:homeid',
  name: 'home',
  component: Home
}
...

此时,我们在使用下述路径时均映射为同一个组件

/home/1
/home/2
/home/3
...

动态路由参数变化

  当从  /home/1 导航到 /home/2,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

  此时,可以使用 beforeRouteUpdate 钩子来进行一些单独的更新操作

beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /home/:homeId,在 /home/1 和 /home/2 之间跳转的时候,
    // 由于会渲染同样的 Home 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
    console.log('beforeRouteUpdate被调用:在当前路由改变,但是该组件被复用时调用')
// to 和 from 分别代表转换前后的 route 对象,可以直接获取 name、path、query 等属性,此时页面还没有渲染,可以做一些事
console.log(to) next() }

编程式路由导航

  不借助 <router-link> 组件,也可实现路由跳转,比如我们想使用 Button 按钮控制路由跳转,就可以绑定如下方法:
// push 跳转
this.$router.push({
   name:'home',
   params:{
      id:xxx,
      title:xxx
   }
})

// replace 跳转
this.$router.replace({
   name:'about',
   params:{
      id:xxx,
      title:xxx
   }
})
this.$router.forward() // 前进
this.$router.back() // 后退
 // 可前进也可后退,参数为一个number,1为前进1步,-2为后退两步,0为刷新页面
this.$router.go(1)

缓存路由组件

  当我们想让不展示的路由组件保持挂载,不被销毁,可以采用 keep-alive 组件。
  如下所示,include 表示指定的缓存路由(参数为路由的name属性),若不指定,则默认缓存 <router-view> 展示的所有路由,如想指定多个,则可用数组
<keep-alive include="home"> 
   <router-view></router-view>
</keep-alive>

路由守卫

  通常用来对路由进行权限控制

// 路由配置
routes:[
    {
        name:"about",
        path:"/about",
        component: About,
        // 路由元信息,可以存点路由独有的信息
        meta:{
            // 是否需要路由守卫权限校验,true为需要,false或不写为不需要直接跳转
            isAuth:true,
        }
    },
    {
        name:"home",
        path: "/home",
        component:Home,
        meta:{
            isAuth: true,
        }
    }
]

全局守卫

  所有路由都要执行

全局前置守卫

  切换之前初始化时 被调用

  下述代码中,若 a = 2,则进行切换时什么也不会发生

  next() 方法不传入参数表示保持默认跳转

  next( false ) 表示拒绝跳转,继续保持当前路由

  next( 路由路径 ) 表示跳转到指定路由。路由路径既可以是 route 对象,也可使是 配置项中的 path

    此处说一下 route 和 router:

      我们在路由组件的 this 中既可以拿到 $route,也可以拿到 $router,那么这俩有什么区别呢?

      其实 route 就是当前路由对象,里面包括 path,name,params,meta 等等配置项信息,而 router 就是 VueRouter 实例化的全局路由对象

const a = 1
// 全局前置路由守卫
// to:去哪, from: 来自哪, next():放行
router.beforeEach((to, from, next)=>{
    console.log("to:");
    console.log(to);
    console.log("from:");
    console.log(from);
    if (to.meta.isAuth){  // 是否需要校验权限
        // next()是正确运行路由,此处若条件不符合,则无法执行路由
        if( a === 1){
            next()
        }
    }else {
        next()
    }
})

  如下所示,to 和 from 参数分别表示上一个路由和下一个路由对象

全局后置守卫

  切换之后初始化时 被调用,若没有成功通过,则不会调用

// 全局后置路由守卫
// 切换之后和初始化时候被调用
// to:去哪, from: 来自哪
// 没next,因为已经切过去了
router.afterEach((to, from)=>{
    // do something
})

独享路由守卫

   直接在配置项中,为某个路由配置路由守卫(只有前置守卫,没有后置守卫)

// 路由配置
routes:[
    {
        name:"about",
        path:"/about",
        component: About,
        meta:{
            isAuth:true,
        },
     // 独享路由守卫 beforeEnter:((to, from, next)
=>{ // 逻辑和全局前置一样 }) } ]

组件内路由守卫

  配置在组件当中的钩子

//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
  // 注意,此时不能使用 this 获取组件实例,因为还没构建完成
  next(vm =>{
    console.log(vm) // 可以在此处使用组件实例
  })
},
//离开守卫:通过路由规则,离开该组件时被调用 beforeRouteLeave (to, from, next) { }

路由守卫执行顺序

  1.首先可以看到,刚进入时,没有进入任何路由,在初始化阶段会执行全局前置守卫全局后置守卫

 

   2.进入 About 展示页,可以看到,路由守卫执行顺序为:全局前置守卫 => 独享守卫 => 组件前置守卫 => 全局后置守卫

  3.再进入 Home 展示页,可以看到,路由守卫执行顺序为:组件后置守卫(from) => 全局前置守卫 => 独享守卫 => 组件前置守卫 => 全局后置守卫

 

 

   通过上述案例,可以总结出守卫执行流程,从 From 路由 切换为 To 路由时,执行顺序为:

    1.From 组件后置守卫

    2.全局前置守卫

    3.To 独享路由守卫

    4.To 组件前置守卫

    5. 全局后置守卫

两种路由模式

  Vue 中可以选择路由模式,分别为 hashRouter 和 historyRouter。

const router = new VueRouter({
  routes,
  // mode: "hash",默认为 "hash"
  mode: "history"    
})

  二者最大的不同就是 url 中是否有 #,对于url来说,#后为url的hash(参考URL API),在发送http请求时,不会保留。

  hashRouter 将路由路径与 url 用#分隔开,网页刷新时可以保持正常刷新。但因为url中#的存在,在某些校验中可能会导致不合法

  historyRouter 较为美观,但刷新网页时需要后端辅助,否则会出现 404

路由懒加载

  路由懒加载,即按需加载,就是把路由组建单路打包成1个或多个 js 文件,从整个项目的 js 文件中分离开,在需要的时候才进行加载。

  配置如下所示:

// router/index.js
import VueRouter from "vue-router"

// 此情况没有指定 webpackChunkName,每个组件会打包成一个 js 文件 const School
= () => import("../src/pages/School.vue") const Student = () => import("../src/pages/Student.vue") export default new VueRouter({ routes:[ { path:"/School", component: School, }, { path:"/Student", component: Student, }, ] })

  添加 webpackChunkName 可以所有路由组件打包成一个 js 文件

const School = () => import(/* webpackChunkName: 'ImportFuncDemo' */ "../src/pages/School.vue")
const Student = () => import(/* webpackChunkName: 'ImportFuncDemo' */ "../src/pages/Student.vue")

 

posted @ 2022-12-24 19:09  邢韬  阅读(76)  评论(0编辑  收藏  举报