VueRouter | 使用总结

213 阅读4分钟

安装

npm install vue-router

模式

hash

常用作锚点在页面内导航,改变URLhash部分不会引起页面刷新
通过hashchange事件监听URL的变化,改变的方式有:

  1. 通过浏览器前进后退改变URL
  2. <a>标签改变URL
  3. window.location改变URL
location.hash // '#/'
location.hash = '/a'
addEventListener('hashchange',(e)=>{...})

history

提供了pushStatereplaceState方法改变URL,改变URLpath部分不会引起刷新

  1. 浏览器前进、后退改变URL会触发popstate事件
  2. 使用pushStatereplaceState方法和<a>标签不会触发popstate事件
  3. 可通过historygobackforward方法触发popState事件
  4. 可以拦截pushStatereplaceState调用和<a>标签的点击事件检测URL变化
history.pushState({state},'','/b')
history.replaceState({state},'','/b')
addEventListener('popstate',(e)=>{...})

起步

src目录下新建router/index.ts

import { createRouter, createWebHistory, createWebHashHistory, RouteRecordRaw } from 'vue-router'

const routes: Array<RouteRecordRaw> = [{
    path: '/',
    name: 'pageA',
    component: () => import(../components/A.vue),
},{
    path: '/b',
    name: 'pageB',
    component: () => import(../components/B.vue),
    children: [...]
}]

export default createRouter({
    history: createWebHashHistory(), // hash模式
    routes
})

main.js中注册router

import router from './router'
creareApp(app).use(router).mount('#app')

使用

切换路由

  1. 组件方式切换
<router-link to='/b'>b.vue</router-link>
<router-link :to={ path: '/b' }>b.vue</router-link>
<router-link :to={ name: 'pageB' }>b.vue</router-link>
  1. 函数方式切换
import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/b')
router.push({ name:'pageB' })
  1. 路由切换记录

路由在切换时,浏览器会保存路由的历史切换记录,方便使用者前进后退

router.go() // 前进
router.back() // 后退

使用replace进行路由切换,不会保存路由切换记录

<router-link replace to='/b'>b.vue</router-link>
或
router.replace('/b')

展示内容

<router-view></router-view>

路由传参

1. Query路由传参

传递参数

const queryObj = {...}
const { id,name } = queryObj

<router-link :to='`/b?id=${id}&name=${name}`'>b.vue</router-link>
或
<router-link :to='{ path: '/b', query: queryObj }'>b.vue</router-link>
或
router.push({
    path: '/b',
    query: queryObj
})

接收参数

import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query) //queryObj

2. Params路由传参

传递参数

const paramsObj = {...}

<router-link :to='{ name: 'b', params: paramsObj }'>b.vue</router-link>
或
router.push({
    name: 'pageB',
    params: paramsObj
})

接收参数

import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params) //paramsObj

动态路由传参

传递参数

// router/index.ts
const routes: Array<RouteRecordRaw> = [
    ...
    ,{
        path: '/b/:id/:name', // ':'动态参数
        name: 'pageB',
        component: () => import(../components/B.vue),
        children: [...]
    }
]

// App.vue
const paramsObj = {...}
const { id,name } = paramsObj

<router-link :to='`/b/id=${id}/name=${name}`'>b.vue</router-link>
或
router.push({
    name: 'pageB',
    params: id
})

接收参数

import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params) //paramsObj

区别

  1. query传参可用pathnameparams必须用name方式传参,path无效
  2. query传递的参数会显示在地址栏中;params则保存在内存中,刷新会丢失
  3. query路由配置不需要设置参数;params必须设置

3. props传参

当路由对象的props属性设置为trueroute.params将被设置为组件的props

// router/index.ts
const routes: Array<RouteRecordRaw> = [
    ...
    ,{
        path: '/b/:id/:name', // ':'动态参数
        name: 'pageB',
        props: true,
        component: () => import(../components/B.vue),
        children: [...]
    }
]

// b.vue
props: ['id', 'name']

嵌套路由

// router/index.ts
const routes: Array<RouteRecordRaw> = [
    ...
    ,{
        path: '/b',
        component: () => import(../components/B.vue),
        children: [ //嵌套子路由
            { path: '', component: () => import(../component/C.vue) },
            { path: 'd', component: () => import(../component/D.vue) },
        ]
    }
]

命名视图

可以在同一级路由中展示更多的路由视图,让一个组件有多个路由渲染出口。

// router/index.ts
const routes: Array<RouteRecordRaw> = [
    {
        path: '/',
        components: {
            default: () => import(../components/content.vue),
            headrt: () => import(../components/header.vue),
            footer: () => import(../components/footer.vue),
        }
    }
]

//App.vue
<router-view name='header'></router-view> //header
<router-view></router-view> //default
<router-view name='footer'></router-view> //footer

重定向 redirect

访问具有redirect属性的路由时,会重定向到目标路由

redirect: '/target' // 字符串形式
redirect: { path: '/target' } // 对象形式
redirect: (to) => ({ path: '/trget', query: {...queryObj} }) //函数形式,可以传参

别名 alias

alias中的属性是路由的别名,以路由别名跳转可以切换到对应的路由

alias: ['/root', '/root1', '/root2'] // 注意不要跟其他路由名冲突

导航守卫

全局前置守卫

路由跳转前执行

// router/index.ts
// 路由跳转权限判断
const allowedRoute = ['/', '/a', '/b']

router.beforeEach((to, from, next)=>{
    const token = localStorage.getItem('token')
    if( allowedRoute.includes(to.path) || token ){
        next()
    } else {
        next({ path: '/' })
    }
})

to: 即将要跳转到的路由对象
from: 即将要离开的路由对象
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed
next('/')next({ path: '/' }): 跳转到一个不同的地址
next(false): 中断当前导航

全局后置守卫

路由跳转后执行

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

路由元信息

通过meta属性可以定义路由的元信息,附加自定义的数据

  • 权限校验标识。
  • 路由组件的过渡名称。
  • 路由组件持久化缓存 (keep-alive) 的相关配置。
  • 标题名称
// router/index.ts
const routes: Array<RouteRecordRaw> = [
    ...
    ,{
        path: '/b',
        meta: {title: '页面B'},
        component: () => import(../components/B.vue)
    }
]

router.beforeEach((to, from, next) => {
  document.title = to.meta.title
  next()
})

ts扩展RouteMetae接口

// router/index.ts
// 扩展元信息类型
declare module 'vue-router' {
    interface RouteMeta {
        title?: string,
        ...
    }
}

跳转过度效果

// router/index.ts
// 使用animate.css动画过渡
const routes: Array<RouteRecordRaw> = [
    ...
    ,{
        path: '/b',
        meta: {transition: 'animate__xxx'}, 
        component: () => import(../components/B.vue)
    }
]

// 
<router-view #default={route,Component}>
    <transition :enter-active-class='`animate__animated ${route.meta.transition}`'>
        <component :is='Component'></component>
    </transition>
</router-view>

滚动行为 scrollBehavior

切换路由时,控制、保持页面滚动的位置

createRouter({
    history: createWebHashHistory(),
    scrollBehavior: (to, from, savePosition)=>{
        savePosition ? savePosition : { top:250 }
    },
    routes
})
  • scrollBehavior方法接收tofrom路由对象;
  • 第三个参数savedPosition当且仅当popstate导航 (通过浏览器的 前进/后退 按钮触发) 时才可用,保存页面滚动位置
  • scrollBehavior返回滚动位置的对象信息:{ left: number, top: number }

动态路由

  1. http请求获取角色权限的路由信息
const result = await axios.get('.../login', params: loginMessage)
  1. 根据获取的路由信息进行处理
  2. 通过router.addRoute动态添加路由
handledResult.data.routes.forEach((route)=>{
    router.addRoute({
        path: route.pathname: route.name,
        component: () => import(`.../views/${route.component}`)
    })
})
  1. router.getRoute获取路由

添加路由

const routeObj = { path:... , name:... , component:... , ... }
router.addRoute(routeObj)

name要唯一;否则添加相同name属性的路由对象时,会覆盖前者

删除路由

router.removeRoute( name: string ) // 按 name 属性删除

查看路由

router.hasRoute( name: string ) // 查看是否有此路由
router.getRoutes() // 返回包含所有路由的数组