路由

180 阅读3分钟

路由是什么

后端路由:根据不同的用户URL请求去执行后端的不同业务返回不同的内容,本质上是URL请求地址与服务器资源之间的对应关系。

前端路由:不同的网址对应各自的页面,本质就是用户事件与事件处理函数之间的对应关系。

vue-router介绍

SPA (Single Page Application)单页面应用程序,整个网站只有一个页面对于浏览器而言一份html文件就是一个网页所以整个网站只有一份html文件,内容的变化通过AJAX局部更新实现,同时支持浏览器地址栏的前进和后退操作。缺点是不利于SEO(搜索引擎优化),优点就是高内聚,低耦合,代码易于维护和迭代。

前端路由就是SPA应用的核心技术,判断当前网址的变化然后根据路由地址切换html文件中对应的组件。vue-router就是专门做切换组件的功能,它是一个单独的技术,依赖vue。

vue-router环境的集成采用官方脚手架cli去自动生成。

在main.js入口文件中引入vue-router

//main.js
import Vue from 'vue'
import App from './App.vue'
//引入路由,会默认去该文件夹下引入index.js的入口文件
import router from './router'
new Vue({
  //挂载路由到整个项目中
  router,
  render: h => h(App)
}).$mount('#app')

挂载路由到整个项目中主要目的是监听地址栏的改变,然后router-view组件就可以根据不同的地址加载项目中不同的组件,就会显示不同的页面

在App.vue中写 <router-view></router-view>

//App.vue
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  
};
</script>

<style lang="scss">

</style>

项目中的App组件一定会显示,所以引入router-view组件。router-view组件会根据路由地址去加载不同的组件,页面就显示不同的页面

路由入口文件的配置,进行路由统一管理,网站不同的网页就在此处注册对应的路由地址。

// router目录下的index.js
//引入Vue,webpack打包时如果已经打包过了的文件就不会再进行打包
//这行代码是为了当前文件中使用Vue不报错但是实质打包时并不会打包,因为main.js中已经打包过了
import Vue from 'vue'

// 引入路由插件
import VueRouter from 'vue-router'

// 引入首页组件,一开始就会打包,因为首页一般是用户直接访问的页面,不需要懒加载。
import HomeView from '../views/home/index.vue'

// 给组件的原型链绑定功能:this.$router this.$routes
Vue.use(VueRouter)

// 注册路由地址,不同的地址对应不同的组件
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/login',
    name: 'login',
    // 组件懒加载,当需要用到该组件时才去加载组件
    component: () => import('../views/login/index.vue')
  },
  {
    path:'/goods',
    name:'goods',
    component:()=>import('@/views/goods/index.vue')
  }
]
// 配置路由规则
const router = new VueRouter({
  mode: 'history',
  routes
})

export default router

入口文件主要功能就是配置路由规则和注册路由地址以及给组件原型链中绑定路由的功能也就是路由对象和路由信息。

每个路由规则都是一个配置对象,其中至少包含path 和component 两个属性。path 表示当前路由匹配的地址栏中的网址,component 表示当前路由对应要加载的组件。path跟router-link标签里的to属性中的地址要一样,不能写错了。

跳转页面

router-view会进行路由地址匹配,router-view会替换为匹配到的组件,就会把匹配到的组件内容渲染到页面。

router-link相当于a标签,给我们提供跳转到某个路由的功能,如果没有匹配到路由就会跳转失败。

router-link和a标签的区别:a标签会请求服务器然后刷新网页 因此用在链接外部网站。router-link渲染到页面也是a标签,但是只是改变了地址栏的网址并没有重新加载网页,因为路由的底层就是采用的 history去监听地址栏的变化,然后把当前App组件中的router-view切换了,因此这种跳转用在网站内部的路由跳转。

跳转有标签跳转和编程式跳转,编程式跳转用JS代码来进行跳转,就可以做业务的逻辑判断,根据不同的条件选择跳转的页面。

<router-link to="/goods">详情页</router-link>
<router-link :to='{path:"/goods"}'></router-link>
编程式跳转: this.$router.push({path:"/goods"})
//this.$router是绑在原型链上的路由对象

路由传参

在跳转路由时,可以给路由对应的组件内传值,路由传参数有两种方式。

query传参

query传参是指把传入的参数拼接在网址中的query字段中

在router-link上的to属性传值的语法

标签跳转传参
1.直接再地址栏中拼接参数
to=/path?参数名=值
<router-link to="/goods?id=1&title=启示录">详情页</router-link>

2.传入一个query对象
<router-link :to="{path:'/goods',query:{id:1,title:'启示录'}}">详情页</router-link>

编程式跳转传参
this.$router.push("/goods?id=1&title=启示录")
this.$router.push({path:"/goods",query:{id:1,title:'启示录'}})

在路由匹配的组件件内获取参数,用this.route是路由信息对象,包含了路由跳转携带的信息。目标页面中在created之后的所有地方用this.route是路由信息对象,包含了路由跳转携带的信息。目标页面中在created之后的所有地方用this.route.query 接受获取数据,如果没有传参 这个值就没有

this.$route.query//获取query参数

image.png

动态路由 (params传参)

动态路由传参指把参数放在网址中的pathname中,路由匹配只会匹配前面的,后面的变量名是任意的,目标组件就可以根据路由信息中的id名获取传入的参数

//注册动态路由
{
    //id是变量名
    path:'/shop/:id',
    name:'shop',
    component:()=>import('@/views/shop/index.vue')
  }
  
标签跳转传参
1.<router-link to="/news/参数">news</router-link>
<router-link to="/shop/goldenstar">shop页面</router-link>

2.<router-link :to="{name:"news",params:{id:参数}}">news</router-link>
<router-link :to="{name:'shop',params:{id:'goldenstar'}}">shop页面</router-link>

编程式跳转传参
1.this.$router.push("/news/参数")
this.$router.push("/shop/goldenstar")

2.this.$router.push({name:"news",params:{id:参数}})
this.$router.push({name:'shop',params:{id:'goldenstar'}})
id变量名和注册路由时写的变量名要一致,必须用name跳路由

接收数据
目标页面的created之后的所有地方(只要可以访问this)
用this.$route.params获取数据,如果没有传参这个值就没有

image.png

注册子路由

1.注册子路由

注册子路由
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
      // 注册路由地址也就是该页面对应的网址
    path: '/gloria',
    
    // 命名路由,用于动态路由做跳转
    name: 'gloria',
    
    // 该页面要加载的组件
    component: () => import('../views/gloria/index.vue'),
    
    //注册子路由
    children: [
      {
      
      没有加/,表示相对相对网络路径,相对于一级路由,需要先匹配上父级路由才能匹配子路由,路由地址拼接在当前网址后面
        path: "hyomin",
        name:"hyomin",
        component:()=>import('@/views/gloria/hyomin/index.vue')
      },
      {
        path: "jessica",
        name:"jessica",
        component:()=>import('@/views/gloria/jessica/index.vue')
      },
      {
      
      有/,表示相对根网络路径,在网址的端口号后面直接拼接/gloria/xwlb
        path: "/gloria/xwlb",
        name:"xwlb",
        component:()=>import('@/views/gloria/jessica/index.vue')
      }
    ]
  }
]

2.使用子路由,需要在父级组件中引入router-view组件

<template>
  <div>
    <h1>gloria</h1>
    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style>
</style>

3.切换路由,同理用标签跳转或者编程式跳转的方式,为了避免路由嵌套过多用相对网络路径而导致跳转出错,建议在跳转时path或者name全都写相对网络根路径。

<router-link to="/gloria/hyomin">去gloria的子路由hyomin</router-link>

2.gif

星号通配路由

*代表所有匹配都通过,星号路由表示用户随便输入的网址,没有任何路由可以匹配就找不到任何组件,就匹配星号路由。注意星号路由需要写在最后,匹配是从前往后开始,一旦匹配上了就不会再进行匹配。

// 注册路由
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/gloria',// 注册路由地址也就是该页面对应的网址
    name: 'gloria',// 命名路由,用于动态路由做跳转
    component: () => import('../views/gloria/index.vue'),// 该页面要加载的组件
    children: [
      {
        path: "hyomin",
        name:"hyomin",
        component:()=>import('@/views/gloria/hyomin/index.vue')
      },
      {
        path: "jessica",
        name:"jessica",
        component:()=>import('@/views/gloria/jessica/index.vue')
      },
      {
        path: "/gloria/xwlb",
        name:"xwlb",
        component:()=>import('@/views/gloria/xwlb/index.vue')
      }
    ]//注册子路由
  },
  {
    path:'/*',
    component:()=>import('@/views/err/index.vue')
  }
]

2.gif

路由重定向

redirect代表重定向,匹配路由地址时重新匹配另外的路由地址。比如地址栏用户输入第一级路由的网址,自动帮他重定向到到第一级路由的子路由的其中一个。

 {
    path: '/gloria',// 注册路由地址也就是该页面对应的网址
    name: 'gloria',// 命名路由,用于动态路由做跳转
    redirect:"/gloria/hyomin",
    component: () => import('../views/gloria/index.vue'),// 该页面要加载的组件
    children: [
      {
        path: "hyomin",
        name:"hyomin",
        component:()=>import('@/views/gloria/hyomin/index.vue')
      },
      {
        path: "jessica",
        name:"jessica",
        component:()=>import('@/views/gloria/jessica/index.vue')
      },
      {
        path: "/gloria/xwlb",
        name:"xwlb",
        component:()=>import('@/views/gloria/xwlb/index.vue')
      },
      // 子路由的星号路由
      {
        path:"*",
        component:()=>import('@/views/gloria/jessica/index.vue')
      }
    ]//注册子路由
  }

2.gif

this.$router的其他函数补充

this.$router.push表示向网址记录中新添加一条历史记录,等同于history.pushState

this.$router.replace表示替换当前的历史记录,等同于history.replaceState

//replace跟push很像也会跳转页面,但不会向 history 添加新记录,而是替换当前的history记录
this.$router.replace({path:"/home"})

前进和后退相当于浏览器的顶部箭头按钮

this.$router.go(1)// 在浏览器记录中前进一步,等同于 history.forward()
 
this.$router.go(-1)// 后退一步记录,等同于 history.back()
 
this.$router.go(3)// 前进 3 步记录
 
this.$router.go(-100)// 如果 history 记录不够用,那就默默地失败,不会跳转页面也不会报错

前端路由模式

前端路由有两种模式:hash 模式和 history 模式。

配置路由规则
const router = new VueRouter({
  mode: 'history',
  routes
})
mode表示底层切换组件的方式是使用的H5window.history的技术

history模式:监听地址栏的pathname的变化,把前端路由的路径拼接在真实 URL 的端口号后面。当监听到地址栏状态发生变化时切换router-view渲染的组件达到切换新网页的效果。因为是监听地址栏的pathname的变化,pathname会发送给后端服务器,所以首先前端路由不能和后端路由同名,其次后端需要配一个星号路由用于读取网站的html文件并发送给前端,否则URL匹配不到任何静态资源将返回404错误。

hash模式:监听地址栏的hash值的变化,把前端路由的路径用井号 # 拼接在真实 URL 后面。当井号 # 后面的路径发生变化时切换router-view渲染的组件达到切换新网页的效果。hash值不会发送给后端,所以不需要后端配合。