首页 > 技术文章 > vue-router大总结

bingquan1 2022-02-14 21:38 原文

vue-router

  • vue-router 是 vue的一个插件库,专门用来实现 SPA应用。

SPA

  • 单页面 Web 应用(single page web application,SPA)。
  • 整个应用只有 一个完整的页面。
  • 点击页面中的导航链接 不会刷新页面,只会做页面的 局部刷新。
  • 数据需要通过 ajax 请求获取

路由

  • 路由:一个路由就是一组映射关系(key-value)
    • key 作为路径,value可能是 function 或 component
路由的分类(前端路由-后端路由)
  • 前端路由
    • 理解:key 是一个路径,value 是一个 component,用于展示页面内容。
    • 工作过程:当浏览器路径变化时,对应的组件就会显示。
  • 后端路由
    • 理解:key 是一个路径,value 是一个 function,用于处理客户端提交的请求。
    • 工作过程:服务器接受到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据。

基本使用

  1. 安装 vue-router,npm i vue-routeryarn add vue-router

  2. 应用插件:Vue.use(VueRouter)

  3. 编写 router 配置项

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from "vue-router";
    import Vue from "vue";
    // 应用插件
    Vue.use(VueRouter)
    import About from "@/components/路由基本使用/About";
    import Home from "@/components/路由基本使用/Home";
    // 创建路由器并暴露
    export default new VueRouter({
      routes: [
        {
          path: '/about',
          component: About
        },
        {
          path: '/home',
          component: Home
        }
      ]
    })
    
  4. 指定展示位置

    <router-view></router-view>
    
几个注意点
  1. 路由组件通常存放在 pages 文件夹,一般组件通常存放在 components文件夹。
  2. 通过切换,“隐藏”了的路由组件,默认是被销毁的,需要的时候再去挂载。
  3. 每个组件都有自己的 $router属性,里面存储着自己的路由信息。
  4. 整个应用只有一个 routers,可以通过组件的$router属性获取到。

嵌套(多级)路由

  1. 配置路由规则,使用 children配置项:

    // 如下例子
    import Home from './pages/Home.vue';
    import News from './pages/News.vue';
    import Message from './pages/Message.vue';
    export default new VueRouter({
        routes: [
            {
                path: '/home',
                component: Home,
                children: [ //通过 children 配置子级路由
                    {
                        path: 'news', // 此处一定不要写:/news
                        component: News
                    },
                    {
                        path: 'message', // 此处一定不要写:/message,
                        component: 
                    }
                ]
            }
        ]
    });
    

路由的 query参数

  1. 传递参数

    <!-- 跳转并携带 query参数,to的字符串写法 -->
    <router-link to="/home/.../...?id=66&title=Hello">跳转</router-link>
    <!-- 跳转并携带 query参数,对象的写法 -->
    <router-link 
        :to="{
             path: '/home/.../...',
             query: {
             	id: 666,
             	title: 'Hello'
             }
        }"
    >跳转</router-link>
    
  2. 接受参数(路由组件)

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

命名路由

  1. 作用:可以简化路由的跳转。

  2. 如何使用:

    1. 给路由命名:

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

      <!-- 简化前,需要写完整路径 -->
      <router-link to="/demo/test/welcome">跳转</router-link>
      
      <!-- 简化后,直接通过名字跳转-->
      <router-link 
        :to="{
        	name: 'hello'     
        }"
      >跳转</router-link>
      
      <!-- 简化写法配合传递参数 -->
      <router-link 
        :to="{
        	name: 'hello',
          query: {
             id: 66,
             title: '你好'
          }
        }"
      >跳转</router-link>
      

路由的params参数

  1. 配置路由,声明接受 params参数

    {
        path: '/home',
        component: Home
        children: [
            {
                path: '/news',
                component: News
            },
            {
                path: '/message',
                component: Message,
                children: [
                    {
                        name: 'xiangqing',
     					path: 'detail/:id/:title', // 使用占位符声明接受 params参数,
                        component: Detail
                    }
                ]
            }
        ]    
    }
    
  2. 传递参数

    <!-- 跳转并携带 params参数,to的字符串写法-->
    <router-link to="/home/message/xiangqing/66/你好"></router-link>
    
    <!-- 跳转并携带 params参数,to的对象写法 -->
    <router-link 
        :to="{
             	name: 'xiangqing',
                params: {
             		id: 66,
             		title: '你好'
             	}       
             }">跳转</router-link>
    
  • 特别注意:路由携带 params 参数时,若使用 to的对象写法,则不能使用 path配置项,必须使用 name配置!
  1. 接受参数

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

路由的props配置

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

    {
        name: 'xiangqing',
        path: '/detail/:id',
        component: Detail,
        
        // 第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
        props: {x: 66},
        
        // 第二种写法:props为布尔值,则把路由收到的所有 params参数通过props传递给Detail组件
        props: true    
        // 第三种写法:props为函数,该函数返回的对象中每一组key-value都会通过props传递给Detail组件
        // props 第一个参数可以获取到 路由组件Detail的$route
        props($route) {
            return {
                id: $toure.query.id,
                title: $router.query.title
            }
        }
    }
    
  1. 作用:控制路由跳转时操作浏览器历史记录的模式。
  2. 浏览器的历史记录有两种写入方式:分别为 pushreplacepush是追加历史记录,replace是替换当前记录。
    1. 路由跳转默认为 push
  3. 如何开启 replace模式:<router-link replace></router-link>

编程式路由导航

  1. 作用:不借助 <router-link>实现路由跳转,让路由跳转更加灵活。

  2. 具体编码:

    // routers的两个API
    this.$routers.push({
        name: 'xiangqing',
        // 或 query
        params: {
            id: xxx,
            title: xxx
        }
    })
    
    this.$routers.replace({
        name: 'xiangqing',
        params: {
            id: xxx,
            title: xxx
        }
    })
    
    this.$routers.forward() // 前进
    this.$routers.back() // 后退
    this.$router.go() // 可前进可后退
    

缓存路由组件

  1. 作用:让不展示的路由组件保持挂载。

  2. 具体编码:

    // 如果缓存多个 则:include="[组件1、组件2]"
    <keep-alive include="缓存的组件">
    	<router-view></router-view>
    </keep-alive>
    

两个新的生命周期钩子

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

路由守卫

  1. 作用:对路由进行权限控制

  2. 分类:全局前置守卫、独享守卫、组件内守卫

  3. 全局守卫

    // 全局前置守卫:初始化时执行、每次路由切换前执行
    router.beforEach((to, from, next)=> {
        if(to.meta.xxx) { // 判断当前是否需要进行权限控制(meta可以看作是一块空间 需要在路由规则进行配置 存储自己想放的内容,比如标记、标题)
    		if( localStore.getItem('xxx') === 'xxx') {
               next() // 放行
            } else {
                alert('暂无权限查看')
            }
        }else {
            next()
        }
    })
    // 全局后置守卫:初始化后执行、每次路由切换后执行
    router.afterEach((to, from)=>{
        if(to.meta.title) {
           document.title = to.meta.title // 修改网页标题
        }else {
            document.title = 'vue_test'
        }
    })
    
  4. 独享守卫:

    // 加在需要的路由独享的路由规则里
    beforEnter() {
        if(to.meta.xxx) { //判断当前路由是否需要进行权限控制
           if(localStore.getItem('xxx') === xxx) {
              next()
           }else {
               alert('暂无查看权限')
           }
        }else {
            next()
        }
    }
    
  5. 组件内守卫

    //进入守卫:通过路规则,进入该组件时被调用
    beforeRouterEnter(to, from, next) {
        
    }
    // 离开守卫:通过路由规则,离开该组件时被调用
    beforeRouterLeave(to, from, next) {
        
    }
    

路由器的两种工作模式

  1. 对于一个url来说,什么是hash值?—— #及后面的内容就是hash值。
  2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
  3. hash模式:
    1. 地址中永远带着#号,不美观。
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
    3. 兼容性较好。
  4. history模式
    1. 地址干净,美观。
    2. 兼容性和hash模式相比略差。
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务器404的问题。
  • 注:使用history模式存在页面刷新存在404的问题,本质上会把路径带给服务器,服务器不知道是前端路由还是后端路由

    • 解决方案:借助connect-history-api-fallback插件可以解决该问题

      const express = require('express')
      const history = require('connect-history-api-fallback')
      const app = express();
      app.use(history()) // 应用该插件
      app.use(express.static( __dirname +'/static'))
      app.listen(5000, (err)=> {
        if(!err) console.log('服务器启动成功:http://127.0.0.1:5000')
      })
      
      • 在vueRouter中切换模式使用 mode属性来指定
      export default new VueRouter({
        mode: 'hash', // 默认hash
        routes: [
          {},
          {}
        ]
      })
      

推荐阅读