路由

101 阅读4分钟

vue-router

vue的一个插件库,专门用来实现SPA应用(单页面应用)。

路由

  1. 一个路由就是一组映射关系(key和value)
  2. key为路径,value可能为组件(前端路由)或函数(后端路由),前端根据路径展示不同组件
  3. 多个路由需要路由器管理

路由的基本使用

  1. 安装vue-router
npm install vue-router@3 // vue2
  1. 使用插件
import VueRouter from 'vue-router'
Vue.use(VueRouter)
  1. 配置router
// 引入vue-router
import VueRouter from 'vue-router'

// 引入组件
import component1 from '../components/component1'
import component2 from '../components/component2'

// 创建并暴露router
export default new VueRouter({
    // 实例对象下的路由规则
    routes = [
        {
            path: '/first',
            component: component1
        },
        {
            path: '/second',
            component: component2
        }
    ]
})
  1. 路由切换
// active-class配置点击时的高亮样式 to为点击时的匹配路径
<router-link active-classs="active" to="/first">first</router-link>
<router-link active-classs="active" to="/second">second</router-link>
  1. 指定组件展示位置
<router-view></router-view>

注意点

  1. 路由组件通常存放在pages文件夹中,一般组件通常存放在components文件夹
  2. 通过切换,隐藏的路由组件默认被销毁,点击时会再次挂载
  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息
  4. 整个应用只有一个router,可以通过组件的$router属性获取到,每个组件的$router属性相同

嵌套(多级)路由

  1. 配置路由规则,通过children配置子级路由
routes = [
        {
            path: '/first',
            component: component1
        },
        {
            path: '/second',
            component: component2,
            children: [
                {
                    path: 'page1', // 不能写成'/page1'
                    component: pageFirst
                },
                {
                    path: 'page2', // 不能写成'/page2'
                    component: pageSecond
                }
            ]
        }
    ]
  1. 路由跳转
<router-link active-classs="active" to="/second/page1">组件A</router-link>
<router-link active-classs="active" to="/second/page2">组件B</router-link>

路由query参数

  1. 传递参数:跳转并携带参数
// 字符串写法
<router-link :to="/second/page1?id=666&name=hello`">组件A</router-link>
<router-link :to="`/second/page1?id=${xxx}&name=${xxx}`">组件A</router-link>

// 对象写法
<router-link 
    :to={
        path:/second/page1
        query:{
            id: xxx,
            name: xxx
        }
    }
>组件A
</router-link>

2.接收参数:query参数可以从组件$route属性中的query得到

$route.query.id
$route.query.name

命名路由

  1. 给路由配置name属性
routes: [
    {
        path: '/demo',
        component: demo,
        children: [
            {
                path: 'test',
                component: test,
                children: [
                    {
                        name:ceshi,
                        path: 'ceshi',
                        component: ceshi
                    }
                ]
            }
        ]
    }
]
  1. 简化to的写法
// 简化前
<router-link to="/demo/test/ceshi"></router-link>

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

// 结合传参
<router-link 
    :to="{
        name: 'ceshi',
        query: {
            id:666,
            title: 'hello'
        }
    }"
></router-link>

路由params参数

  1. 在配置路由时,必须声明接收params参数
routes: [
    {
        path: '/demo',
        component: demo,
        children: [
            {
                path: 'test',
                component: test,
                children: [
                    {
                        name:ceshi,
                        path: 'ceshi/:id/:title', // 使用占位符声明接收params参数
                        component: ceshi
                    }
                ]
            }
        ]
    }
]
  1. 传递参数
// 字符串写法
<router-link to="/demo/test/ceshi/666/你好"></router-link>

// 对象写法
<router-link 
    :to="{
    // 传递params时,不能使用path属性,必须用name跳转
        name: 'ceshi',
        params: {
            id:666,
            title: 'hello'
        }
    }"
></router-link>
  1. 接收参数:params参数可以从组件$route属性中的params得到
$route.query.id
$route.query.name

路由的props

作用可以让路由组件更方便的接收到参数

{
    name: 'ceshi',
    path: 'ceshi/:id'
    component: ceshi,
    
    // 对象写法
    props: {id: 666}
    
    // 布尔值写法,当props为true,则把路由收到的所有params参数传给组件,同时组件用props接收
    props: true
    
    // 函数写法,接收组件的$route为参数,返回值中每一组key-value都会通过props传递给组件
    props($route){
        return {id: $route.query.id}
    }
}

<router-link>pushreplace属性

  1. 浏览器的历史记录有两种写入方式:push(追加记录)和replace(替换当前记录)。作用:控制路由跳转时操作浏览器历史记录的模式。路由跳转时默认是push模式。

image.png
上图中/about/home均为push方式,/newreplace方式,从/new后退到上一个路由则为/about

  1. 开启replace模式
<router-link replace></router-link>
// 等同于
<router-link :replace="true"></router-link>

编程式路由导航

  1. 不借助<router-link>,使用API实现路由跳转
// $router的两个API
// 跳转并保留上一个路由
this.$router.push({
    name: 'detail',
    params: {
        id: 666,
        title: 'hello'
    }
})

// 跳转并替换上一个路由
this.$router.replace({
    name: 'detail',
    params: {
        id: 666,
        title: 'hello'
    }
})

this.$router.forward() // 前进
this.$router.back() // 后退
this.$router.go() // 可前进也可后退,参数为步数

缓存路由组件

<keep-alive>让不展示的组件保持挂载,不销毁。

// 没有include则默认缓存所有在<router-view>展示的组件

// 缓存一个路由组件
<keep-alive include="组件名">
    <router-view></router-view>
</keep-alive>

// 缓存多个路由组件
<keep-alive :include="[组件1, 组件2]">
    <router-view></router-view>
</keep-alive>

路由组件的生命钩子

  1. 路由组件所独有的两个钩子,用于捕获路由组件的激活状态
  2. activated路由组件被激活时触发,deactivated路由组件失活时触发

路由守卫

  1. 路由守卫对路由进行权限控制(鉴权),包括全局守卫、独享守卫和组件内守卫
  2. 全局守卫包括全局前置路由守卫和全局后置路由守卫
const router = new VueRouter({
    routes = [
        {
            name: 'xxx',
            path: '',
            meta: {isAuth: true}
        }
    ]
})

// 全局前置路由守卫...
// 全局后置路由守卫...

export default router
// 全局前置守卫:初始化时执行,每次路由切换前执行
// to为目的路由,from为源路由
router.beforeEach((to, from, next) => {
    if (to.meta.isAuth){ // 判断当前路由是否需要权限控制(鉴权)
        if (localStore.getItem('xxx') === 'xxx'){ // 权限控制的具体规则
            next() // 放行
        }else {
            alert('暂无权限')
        }
    }else {
        next() //  放行 
    }
})

// 全局后置守卫:初始化时执行,每次路由切换后执行
router.afterEach((to, from) => {
    if (to.meta.title) {
        document.title = to.meta.title // 修改网页title
    }else {
        document.title = 'xxx'
    }
})
  1. 独享路由守卫为某个路由所独享的,只有前置独享守卫
{
    // ...
    beforeEnter((to, from, next) => {})
}
  1. 组件内守卫必须通过路由规则切换组件才能触发
// 进入守卫:进入该组件时被调用
beforeRouteEnter(to, from, next){}

// 离开守卫:离开该组件时被调用
beforeRouteLeave(to, from, next){}

路由器的两种工作模式

路由器的工作模式包括hash和history。 hash值是url中#及其后面的内容,hash值不会包含在HTTP请求中,即不会带给服务器。

hash模式

  1. 地址中永远带着#
  2. 若以后将地址通过第三方手机app分享,当app校验严格时,带#的地址会被标记为不合法
  3. 兼容性较好

history模式

  1. 地址不带#
  2. 兼容性较hash模式略差
  3. 应用部署上线后需要后端人员支持,解决页面刷新呈现404的问题