22. 路由(Vue-Router)

22.1 基本使用

  1. 安装vue-router, 命令: npm i vue-router
  2. 应用插件: Vue.use(VueRouter)
  3. 编写router配置项:

    src/router/index.js

    //引入VueRouter
    import VueRouter from 'vue-router'
    //创建router实例对象并暴露
    export default new VueRouter({
        //管理一组一组的路由规则
        routes:[
            {
                //导航路径
                path:"/home",
                component:()=>import('../components/Home')
            },
            {
                path:"/about",
                component:()=>import('../components/About')
            }
        ]
    })
  4. 实现切换(active-class可配置高亮样式)

    <router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
    <router-link class="list-group-item" active-class="active" to="/about">About</router-link>
  5. 指定展示位置

    <router-view></router-view>

22.2几个注意点

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹
  2. 通过切换,'隐藏'了的路由组件,默认是被销毁掉的,需要的时候再去挂载
  3. 每个组件都有自己的$route属性,里面存储这自己的路由信息
  4. 整个应用只有一个router,可以通过组件的$router属性获取到

22.3 嵌套路由(多级路由)

  1. 配置路由规则,使用children配置项:
  2. routes:[
        {
            //导航路径
            path: "/home",
            component: () => import('../pages/Home'),
            children:[
                {
                    path:"news",
                    component:()=>import('../pages/News')
                },
                {
                    path:"message",
                    component:()=>import('../pages/Message')
                }
            ]
        },
        {
            path:"/about",
            component:()=>import('../pages/About')
        }
    ]
  3. 跳转(要写完整路径):

    <router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>

22.4 路由的query参数

  1. 传递参数

    Message.vue

    <template>
      <div>
        <ul>
          <li v-for="m in messageList" :key="m.id">
            <!--跳转路由并携带query参数(to的字符串写法)-->
            <!--<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>-->
            <!--跳转路由并携带query参数(to的对象写法)-->
            <router-link :to="{
              path:'/home/message/detail',
              query:{
                id:m.id,
                title:m.title
              }
            }">{{m.title}}</router-link>
          </li>
        </ul>
        <router-view></router-view>
      </div>
    </template>
    <script>
    export default {
      name: "Message",
      data() {
        return {
          messageList: [
            {id: "001", title: "消息001"},
            {id: "002", title: "消息002"},
            {id: "003", title: "消息003"},
          ]
        }
      }
    }
    </script>
    <style scoped>
    </style>
  2. 接收参数

    Detail.vue

    <template>
      <ul>
        <li>消息编号: {{ $route.query.id }}</li>
        <li>消息标题: {{ $route.query.title }}</li>
      </ul>
    </template>
    <script>
    export default {
      name: "Detail"
    }
    </script>
    <style scoped>
    </style>
  3. src/router/index.js

    //引入VueRouter
    import VueRouter from 'vue-router'
    //创建router实例对象并暴露
    export default new VueRouter({
        //管理一组一组的路由规则
        routes:[
            {
                //导航路径
                path: "/home",
                component: () => import('../pages/Home'),
                children:[
                    {
                        path:"news",
                        component:()=>import('../pages/News')
                    },
                    {
                        path:"message",
                        component:()=>import('../pages/Message'),
                        children:[
                            {
                                path:"detail",
                                component:()=>import('../pages/Detail')
                            }
                        ]
                    }
                ]
            },
            {
                path:"/about",
                component:()=>import('../pages/About')
            }
        ]
    })

22.5 命名路由

  1. 作用: 可以简化路由的跳转
  2. 如何使用

    1. 给路由命名:

      //引入VueRouter
      import VueRouter from 'vue-router'
      //创建router实例对象并暴露
      export default new VueRouter({
          //管理一组一组的路由规则
          routes:[
              {
                  name:"home",
                  //导航路径
                  path: "/home",
                  component: () => import('../pages/Home'),
                  children:[
                      {
                          name:"news",
                          path:"news",
                          component:()=>import('../pages/News')
                      },
                      {
                          name:'message',
                          path:"message",
                          component:()=>import('../pages/Message'),
                          children:[
                              {
                                  name:"detail",
                                  path:"detail",
                                  component:()=>import('../pages/Detail')
                              }
                          ]
                      }
                  ]
              },
              {
                  path:"/about",
                  component:()=>import('../pages/About')
              }
          ]
      })
    2. 简化跳转

      <router-link :to="{
        name:'detail',
        query:{
          id:m.id,
          title:m.title
        }
      }">{{m.title}}</router-link>

22.6 路由的params参数

  1. 使用占位符声明接收params参数

    children:[
        {
            name:"detail",
            //使用占位符声明接收params参数
            path:"detail/:id/:title",
            component:()=>import('../pages/Detail')
        }
    ]
  2. 传递参数

    <ul>
        <li v-for="m in messageList" :key="m.id">
            <!--跳转路由并携带params参数(to的字符串写法)-->
            <!--<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>-->
            <!--跳转路由并携带params参数(to的对象写法)-->
            <router-link :to="{
                              name:'detail',
                              params:{
                              id:m.id,
                              title:m.title
                              }
                              }">{{m.title}}</router-link>
        </li>
    </ul>

    注意: 使用对象写法不能使用path传路径,必须使用name指定

  3. 接收参数

    <ul>
        <li>消息编号: {{ $route.params.id }}</li>
        <li>消息标题: {{ $route.params.title }}</li>
    </ul>

22.7 路由的props配置

作用: 让路由组件更方便的收到参数

src/router/index.js

{
    name: "detail",
        //使用占位符声明接收params参数
        path: "detail/:id/:title",
            component: () => import('../pages/Detail'),
                //第一种写法,props值为对象,该对象中所有的属性都会以props的形式传给Detail组件
                // props: {id: "555", title: "XXX"}
                //第二种写法,props值为布尔值,如果该对象为真,则吧路由收到的所有params参数通过props传给Detail组件
                // props:true
                //第三种写法,props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
                props(route){
                return {
                    id:route.params.id,
                    title:route.params.title
                }
            }
}

22.8 <router-link>的replace属性

  1. 作用: 控制路由跳转时操作浏览器历史记录的模式
  2. 浏览器的历史记录有两种写入方式: 分别为pushreplace,push是追加历史记录,replace是替换当前记录.路由跳转时候默认为push
  3. 如何开启replace模式: <router-link replace ......>News<router-link/>

22.9 编程式路由导航

  1. 作用: 不借助router-link实现路由跳转,让路由跳转更加灵活
  2. 具体编码

    //$router的两个API
    this.$router.push({
        name:"detail",
        params:{
            id:xxx,
            title:xxx
        }
    })
    this.$router.replace({
        name:"detail",
        params:{
            id:xxx,
            title:xxx
        }
    })
    this.$router.forward();//前进
    this.$router.back();//后退
    this.$router.go(2)//正数前进,负数后退

22.10 缓存路由组件

作用: 缓存路由组件后,组件将不被销毁

<!--缓存路由组件,include指定要缓存的组件名称,不指定则将缓存所有router-view标签渲染的组件(指定单个)-->
<keep-alive include="News">
    <router-view></router-view>
</keep-alive>
<!--缓存路由组件,include指定要缓存的组件名称(指定多个)-->
<keep-alive :include="['News','Message']">
    <router-view></router-view>
</keep-alive>

22.11 两个新的生命周期钩子

  1. 作用: 路由组件所独有的两个钩子,用于捕获路由组件的激活状态
  2. 具体名字:

    1. activated路由组件被激活时触发
    2. deactivated路由组件失活是触发

22.12 路由守卫

  1. 作用: 对路由进行权限控制
  2. 分类: 全局守卫, 独享守卫, 组件内守卫
  3. 全局守卫

    //引入VueRouter
    import VueRouter from 'vue-router'
    //创建router实例对象并暴露
    const router = new VueRouter({
        //管理一组一组的路由规则
        routes: [
            {
                path:"/",
                redirect:"/login",
                meta:{title:"登录"}
            },
            {
                name:"login",
                path:"/login",
                meta:{title:"登录"},
                component:()=>import('../pages/Login')
            },
            {
                name: "home",
                //导航路径
                path: "/home",
                meta:{title:"主页"},
                component: () => import('../pages/Home'),
                children: [
                    {
                        name: "news",
                        path: "news",
                        //需要权限查看
                        meta:{isAuth:true,title:"新闻"},
                        component: () => import('../pages/News')
                    },
                    {
                        name: 'message',
                        path: "message",
                        //需要权限查看
                        meta:{isAuth:true,title:"消息"},
                        component: () => import('../pages/Message'),
                        children: [
                            {
                                name: "detail",
                                //使用占位符声明接收params参数
                                path: "detail/:id/:title",
                                meta:{title:"详情"},
                                component: () => import('../pages/Detail'),
                                //第一种写法,props值为对象,该对象中所有的属性都会以props的形式传给Detail组件
                                // props: {id: "555", title: "XXX"}
                                //第二种写法,props值为布尔值,如果该对象为真,则吧路由收到的所有params参数通过props传给Detail组件
                                // props:true
                                //第三种写法,props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
                                props(route) {
                                    return {
                                        id: route.params.id,
                                        title: route.params.title
                                    }
                                }
                            }
                        ]
                    }
                ]
            },
            {
                path: "/about",
                meta:{title:"关于"},
                component: () => import('../pages/About')
            }
        ]
    })
    //全局前置路由守卫---初始化的时候被调用,每次路由切换之前被调用
    router.beforeEach((to, from, next)=>{
        //判断当前路由是否需要鉴权
        if(to.meta.isAuth){
            //权限控制的具体规则
            if(localStorage.getItem('name')==='yiyu'){
                //放行
                next()
            }else{
                alert("姓名不对,无权限查看")
                next("/login")
            }
        }else{
            next()
        }
    })
    
    //全局后置路由守卫---初始化的时候被调用,每次路由切换之后被调用
    router.afterEach((to, from)=>{
        //修改网页的title
        document.title=to.meta.title
    
    })
    
    export default router

22.13 独享守卫

beforeEnter(to,form,next) {
    if (to.meta.isAuth) {
        //权限控制的具体规则
        if (localStorage.getItem('name') === 'yiyu') {
            //放行
            next()
        } else {
            alert("姓名不对,无权限查看")
            next("/login")
        }
    } else {
        next()
    }
}

22.14 组件内守卫

<template>
<h2>我是About中的内容</h2>
</template>
<script>
    export default {
        name: "About",
        //进入守卫,通过路由规则,进入该组件时被调用
        beforeRouteEnter(to, from, next) {
            console.log("About---beforeRouteEnter")
            if (to.meta.isAuth) {
                //权限控制的具体规则
                if (localStorage.getItem('name') === 'yiyu') {
                    //放行
                    next()
                } else {
                    alert("姓名不对,无权限查看")
                    next("/login")
                }
            } else {
                next()
            }
        },
        //进入守卫,通过路由规则,离开该组件时被调用
        beforeRouteLeave(to, from, next){
            console.log("About---beforeRouteLeave")
            next()
        }
    }
</script>
<style scoped>
</style>

22.15 路由器的两种工作模式

  1. 对于一个url来说,什么是hash值?----#及其后面的内容就是hash值
  2. hash值不会包含在HTTP请求中,即: hash值不会带给服务器
  3. hash模式:

    1. 地址中永远带着#号,不美观
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
    3. 兼容性好
  4. history模式

    1. 地址干净,美观
    2. 兼容性和hash模式相比略差
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题changeOrigin
最后修改:2023 年 01 月 31 日
如果觉得我的文章对你有用,请随意赞赏