1. 单页面应用(SPA)

  • SPA (single page web application) 应用
  • vue 是单页面应用,所谓单页面应用就是页面发生改变并不会刷新,只是进行路由跳转
  • 单页面应用就是根据 hash 值来变化的,当哈希值改变页面不会发生跳转
  • vue 的单页面需要借助到 vueRouter 进行路由跳转

2. 路由的理解

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

3. 路由的安装与搭建

  • 现在如果使用 npm 安装 vue-router 默认为 vue-router4

  • vue-router4 适配 Vue3vue-router3 适配 Vue2

    npm i vue-router@3
    
  • 创建 router/index.js 文件

    import Vue from "vue";
    import VueRouter from "vue-router";
    
    // 使用插件,使用路由不分前后
    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
        }
      ]
    })
    
    
    import Vue from 'vue'
    import App from './App.vue'
    
    // 导入路径配置
    import router from "./router/index"
    
    Vue.config.productionTip = false
    
    new Vue({
      render: h => h(App),
      // 挂载路由
      router
    }).$mount('#app')
    // 挂载之后会多两个属性 
    // $route:每个组件独享的属性
    // $router:全局的一个属性
    

4. 路由的使用

4.1 基本使用
<!--
  标签:
    router-link:进行路由跳转的按钮,页面会渲染成 a 标签
	router-view:对应路由展示的内容
  属性:
    active-class:对应的路径页,展示对应的 active 样式
  	to:跳转路由的路径
	replace:替换当前浏览器历史记录,路由跳转的时候默认是 push 追加历史记录
-->
<router-link active-class="active" to="/about">点我显示about组件</router-link>
<router-link active-class="active" to="/home">点我显示home组件</router-link>

<router-view></router-view>

注意:

在对路由组件进行切换时,组件会进行创建和销毁

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

4.2 嵌套(多级)路由
export default new VueRouter({
  routes: [
    {
      path: "/about",
      component: About,
      // msg1 和 msg2 为 about 的二级路由
      children: [
        {
          // 一级路由 path 需要加 /,二级路由不需要
          path: "news",
          component: News
        },
        {
          path: "msg",
          component: Msg
        }
      ]
    },
    {
      path: "/home",
      component: Home
    }
  ]
})
<!-- 在一级路由中接着写路由 -->
<h2>我是About组件</h2>
<router-link active-class="active" to="/about/news">显示News</router-link>
<router-link active-class="active" to="/about/msg">显示Msg</router-link>
<router-view></router-view>
4.3 路由传参
  • query参数

    <!-- 传入参数 -->
    <!-- 字符串拼接 -->
    <router-link :to="`/about/msg/detail?id=${item.id}&title=${item.title}`">
      {{ item.title }}
    </router-link>
    
    <!-- 对象携带 query 参数 -->
    <!-- 也可以写 name -->
    <router-link
      :to="{
        path: '/about/msg/detail',
        query: {
          id: item.id,
          title: item.title,
        },
      }"
      >{{ item.title }}</router-link>
    
    <!-- 接收参数 -->
    <router-view></router-view>
    <!-- 
    	在被 router-view 渲染出的组件,可以接收到对应的参数
    -->
    <!-- $route.query -->
    
  • params参数

    // params 需要路由路径配合
    {
      name: "Demo"
      path: '/demo/:id/:title',
      component: Demo,
    }
    
    <!-- 传入参数 -->
    <!-- 字符串拼接 -->
    <router-link :to="`/demo/${item.id}/${item.title}`">
      {{ item.title }}
    </router-link>
    
    <!-- 对象携带 params 参数 -->
    <router-link
      :to="{
        name: 'Demo',
        params: {
          id: item.id,
          title: item.title,
        },
      }"
      >{{ item.title }}</router-link>
    

    注意:params 传参,使用 to 的对象写法,不能使用 path 配置项,必须使用 name 配置

    <!-- 
      接收参数,
      $route.params
    -->
    

5. 路由命名与元信息

5.1 命名路由

添加 name 属性,可以简化路由跳转

{
  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>
5.2 路由元信息

定义路由的时候可以配置 meta 字段:也就是自定义属性

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          meta: { 
            requiresAuth: true 
          }
        }
      ]
    }
  ]
})

6. 路由的props配置

// 传参时的配置
{
  name: "Demo"
  path: '/demo',
  component: Demo,
  // 对象式,这种方式只能传入静态数据
  props: {flag: true}
  
  // 布尔值,把 params 的参数传递给 Demo 组件,只能操作 params 参数
  props: true
    
  // 函数式,这种方式都可以传递,比就好的一种方式
  props($router) {
    return {
      id: $router.query.id,
      title: $router.query.title,
    }
  }
}
// 这里配置项的写法和组件 props 属性是一样的
// 不用担心会重复,因为路由组件是不能通过组件标签名去使用
props: {
  id: String,
  title: String,
}

7. 编程式路由导航

不借助 <router-link> 进行路由跳转

// 向浏览器中追加一个历史记录
this.$router.push({
  // 跳转路径
  // 携带参数
})

// 替换当前历史记录
this.$router.replace({
  // 跳转路径
  // 携带参数
})

// 对浏览器路由历史记录进行操作
// 回退
this.$router.back()

// 前进
this.$router.forward()

// n 正多少就前进多少,n 负多少就后退多少
this.$router.go(n)

8. 缓存路由组件

  • 在路由组件进行切换时,组件经过创建销毁

  • 使用 <keep-alive> 包裹住的路由组件,创建一次后不会在销毁了,也就是缓存

    <!--
      需要在组件中添加 name 属性,才能匹配对应的组件
      include:字符串或正则表达式。只有名称匹配的组件会被缓存。
      exclude:字符串或正则表达式。任何名称匹配的组件都不会被缓存。
      max:数字。最多可以缓存多少组件实例。
    -->
    <keep-alive include="news"> 
      <router-view></router-view>
    </keep-alive>
    
    <!--
      单个写法:include="news"
      多个写法:include="news,msg"
    		  :include="['news', 'msg']"
    -->
    
  • 使用 <keep-alive> 才会触发的两个生命周期钩子

    activated(){
      console.log("激活时触发,显示该组件时触发")
    }
    
    deactivated(){
      console.log("失活时触发,离开该组件时触发")
    }
    

9. 路由守卫

9.1 路由配置信息
{
  fullPath: "路由路径,会包含 query 和 params 参数",
  path: "路由路径,只会包含 params 参数",
  name: "路由命名",
  hash: "路由模式",
  matched: [
    // 包含当前路由的所有嵌套路径片段的路由记录,包括父子
  ],
  meta: {
    // 路由元信息
  },
  params: "参数",
  query: "参数"
}
9.2 全局路由守卫
//全局前置守卫:初始化时执行、每次路由切换前执行
router.beforeEach((to, from, next) => {
  // to:进入哪个路由,配置
  // from:从哪个路由来,配置
  // next:放行,如果不放行路由将会被拦截
  // next 括号中也可以添加跳转路由路径,next('/')、next({path: '/'})、next({name: '/'})
})


//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to, from) => {
  // 后置路由没有 next,都跳完了还怎么拦
})
9.3 路由独享守卫
// 独享直接写在路由配置项中
{
  name: "xxx",
  path:"xxx/xxx",
  component: Xxx,
  beforeEnter(to,from,next){ }
}
9.4 组件内的守卫
// 组件内的守卫,要写在组件中
export default {
  //进入守卫:通过路由规则,进入该组件时被调用
  beforeRouteEnter (to, from, next) { },
  //离开守卫:通过路由规则,离开该组件时被调用
  beforeRouteLeave (to, from, next) { }
}
9.5 完整的导航解析流程
  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

10. 路由器的两种工作模式

  • 对于一个 url 来说,# 及其后面的内容就是 hash 值

  • hash 值不会包含在 HTTP 请求中,hash 值不会带给服务器,也不会发送请求,这就是单页面的原理

  • hash 模式:

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

    1. 地址干净,美观
    2. 兼容性和 hash 模式相比略差
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题

      如果 vue.config.js 配置 publicPath,则 base 需要统一

  • 设置两种模式

    const router = new VueRouter({
      mode: "history/hash"
    })
    
  • node 解决 history 模式刷新页面404

    const express = require("express")
    const history = require("connect-history-api-fallback")
    
    const app = express()
    app.use(history())
    

11. 路由懒加载

  • 因为 Vue 是单页面应用,就导致了第一次进入页面的时候,会加载很久

  • 可以给路由组件进行懒加载,这样只有访问该组件的时候才会加载

    // 写法
    {
      name: "Demo"
      path: '/demo/:id/:title',
      component: () => import('./Foo.vue')
    }
    

12. 重定向与别名

12.1 重定向
// 当访问根路径时,重定向到 home 页
export default new VueRouter({
  routes:[
    {
      path: "/",
      redirect: "/home"
    },
  ]
})
12.2 别名
// 给路由起别名
export default new VueRouter({
  routes:[
    {
      path: "/home",
      alias: "/haha",
      component: Home
    },
  ]
})
<!-- 可以使用 haha 去代替 home,此时页面的 url 也会变成 haha-->
<router-link to="/haha"></router-link>
Logo

前往低代码交流专区

更多推荐