路由导读
1-2.1、什么是路由?
- 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
- key 为路径, value 可能是 function 或 component
1-2.2、路由分类
1、后端路由:
(1)理解:value 是 function, 用于处理客户端提交的请求。
(2)工作过程:服务器接收到一个请求时, 根据请求路径找到匹配的函数 来处理请求, 返回响应数据。
2、前端路由:
(1)理解:value 是 component,用于展示页面内容。
(2)工作过程:当浏览器的路径改变时, 对应的组件就会显示。
第一章节(上)——入门(安装及配置)
1. 安装 vue-router
npm i vue-router --save //注意Vue2与Vue3的路由是互不兼容的,使用Vue3请使用Router4
2. 配置 vue-router
新建 router
文件夹
路径:/src/router
新建 index.js
文件
路径: /src/router/index.js
- 步骤
- 在
router
文件夹下的index.js
中我们进行引入路由,然后创建一个路由器,在路由器中配置路由 - 然后要在
main.js
中进行引入router并进行使用 - 在App.vue中使用
进行存放路由,这个是一个容器(内置组件,可以写在任何位置)
- 有了容器我们就可以往里面放东西了,还记得我们在index.js配置的路由信息吗?
- 使用
,
to决定了我们要跳向哪个位置,to里面填写的内容就是我们填在路由器中的路由的path。通过点击触发path路径然后激活component进行路由跳转。请注意这这个
router-link`是一个a标签
- RouteRecordRaw属性通过源码可以看出联合了
RouteRecordSingleView
,RouteRecordMultipleViews
,RouteRecordRedirect
这三个类型,在继续往下,我们可以看到很多个配置,其中path
与component
是必填的
//index.js文件 import {createRouter,createWebHistory } from 'vue-router' const routes = [ { path:'/',//这两个属性是必传的,这个是显示在路径中的内容 component:() => import('../pages/login.vue')//这个是要通过路由跳转过去的组件位置(就是说我们要去的地方) } ] const router = createRouter({ history:createWebHistory(), routes //路由信息 }) export default router//记得将路由暴露出去
第一章节(下)——路由模式
我们平时在路径中有看到/#/的就是哈希模式(hash),这个哈希不是算法
//Vue2 mode history Vue3 createWebHistory(历史),兼容性较差一点,但路径不显示# //Vue2 mode hash Vue3 createHashHistory(哈希) //Vue2 mode abstact Vue3 createMemoryHistory
- 这个/#/是因为哈希模式是通过
location.hash
去匹配的,我们在控制台中可以打印出'#/'的结果 - 如果在控制台中修改
location.hash
的话,页面中也会进行实时跳转 - 通过监听window上的一个属性
hashchange
我们可以看到跳转之间的变化(哈希模式
)
window.addEventListener('hashchange',(e)=>{ console.log(e) }) //哈希原理:通过监听hashchange我们可以看到HashChangeEvent这个属性里面的 //newURL与oldURL,其实也就是新地址跟旧地址(此地址其实就是路由跳转的变化)
在上面我们演示了哈希的原理,接下来我们看另外的一个常用的,也就是路径中不带#号的History
的原理,是通过popstate
来看的
window.addEventListener('popstate',(e)=>{ console.log(e) }) //通过此属性得到的是PopStateEvent,在里面的state里面我们可以看到 //back(返回路径)current(当前页面)forward(上一个页面) //监听跳转:通过history.pushState({存点东西},'第二个没啥用','第三个是跳转路径'),跳转后不会被浏览器监听到
第二章——命名路由-编程式导航
作用:可以简化路由的跳转。
不借助实现路由跳转,让路由跳转更加灵活
除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
在路由器中的路由中进行使用,name:"xxx,爱叫什么叫什么,你叫yupi也无所谓,英文"
- 使用name命名路由后,我们第一件事情就是去使用了对应路由的地方进行修改
- 比如我们原本是,现在就不是路径了,现在得变成名字了=>
- 注意点:to前面多了冒号,是变成响应式的标记,然后写法变为对象形式
- 稍微提一嘴的a标签(这个router-link会自动转化为a标签,但是跟你直接使用a标签是不一样的,使用router-link的才会是单页面,如果直接使用a标签的话,那其实实际感官上是会抖动一下,然后会刷新页面)
<a href="/reg">rrr</a>
没错啦,上面都是铺垫,接下来才是编程式的路由导航
写法
命名路由
除了 path
之外,你还可以为任何路由提供 name
。这有以下优点:
- 没有硬编码的 URL
params
的自动编码 / 解码。- 防止你在 url 中出现打字错误。
- 绕过路径排序(如显示一个)
步骤
- 引入useRouter
import {useRouter} from 'vue-router'
- 使用router
const router = useRouter()
- 字符串用法
//import { useRouter } from 'vue-router' //const router = useRouter() //请注意,这个toPage是一个按钮,在页面中使用@click进行绑定 const toPage = () => { router.push('/reg') } //TS写法 const toPage = (url:string) => { router.push(url)//这种写法的话就需要自己在上面@click="toPage('这里传入路径')",进行配置了 }
- 对象模式
import { useRouter } from 'vue-router' const router = useRouter() const toPage = () => { router.push({//对象形式的写法 path: '/reg'//path是路径,这里一样是写死了,可以将参数传进来 }) }
- 命名式写法
import { useRouter } from 'vue-router' const router = useRouter() const toPage = () => { router.push({ name: 'Reg'//这里需要注意,在前面设置的也需要进行修改,不能够再传入url了,因为我们这里是命名式写法,需要传入命名(此处是写死的做法,下面是传值式的写法) }) } const toPage = (Name:string) => {//TS写法,不用TS写法的话写个Name就行了 router.push({//一样是对象形式写法 name: Name//传值式写法 }) }
第三章——历史记录
的replace属性
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式:分别为
push
和replace
,push
是追加历史记录,replace
是替换当前记录。路由跳转时候默认为push
- 如何开启
replace
模式:News
- replace官方的解释就是替换当前的记录,可以简单的理解为无痕模式。你无法回退到之前的页面中,你做出的每一个指令都是没有回头路的
- router-link使用方法
<router-link replace to="/">Login</router-link> <router-link replace style="margin-left:10px" to="/reg">Reg</router-link>
- 编程式导航
<button @click="toPage('/')">Login</button> <button @click="toPage('/reg')">Reg</button> import { useRouter } from 'vue-router' const router = useRouter() const toPage = (url: string) => { router.replace(url)//与router-link的区别就是,编程式导航的replace隐藏在js里面 }
go与back
横跨历史
该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步
<button @click="next">前进</button> <button @click="prev">后退</button>
const next = () => { //前进 数量不限于1 router.go(1)//不知能前进,还可以后退,后退就是负数,数字的大小决定前进与后退几步 } const prev = () => { //后退,这个就是纯后退了,按一下退一步 router.back() }
第四章——(路由传参)
Query 路由传参
编程式导航 使用 router push 或者 replace 的时候 改为对象形式新增 query 必须传入一个对象
使用前步骤(复习)
- 引入useRouter,在vue3中需要使用的都要针对性的引入
- 使用(我更愿意称为激活使用),const router = useRouter(),这样后面进行使用的时候就直接router.xxx。本质上其实就是调用useRouter了
- query是写在push里面的,且只能接受一个对象
//子组件login.vue const toDetail = (item:Item) =>{ router.push({ path:'/reg', query:item//item是一个对象 }) } //通过url路径,我们可以看到信息其实已经传过来了
Params路由传参
编程式导航 使用 router push 或者 replace 的时候 改为对象形式并且只能使用 name
,path
是无效的,然后传入 params
- 使用Params来进行传参的话,不能使用path而是使用name。与此同时,query要变化为params,因为我们已经换频道了,现在是params专场,记得在html页面(或者说是template部分)要将
route.query.name
啥的换成route.pamas.name
const toDetail = (item: Item) => { router.push({ name: 'Reg', params: item }) }
注意点:
- pamas的内容是存在内存当中的,这个也是与query传参的一个不同之处,但由此也会造成一个问题,那就是我们一但刷新,这个值是会丢失的
为了解决这个值会丢失的问题,我们延伸出了第三种方式 => 动态路由传参
动态路由传参
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User
组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数
路径参数 用冒号 :
表示。当一个路由被匹配时,它的 params 的值将在每个组件
步骤:
- 修改router.push中的params
params:item//虽然item本身也是对象,但是换成对象形式写会更好 //修改后 params:{ id:item.id//这里取名定义的要跟下面 代码块1中的`动态路由参数`部分的 path对应上(取名是指id,而不是item.id) }
- 进一步改造
import { useRoute } from 'vue-router'; import { data } from './list.json' const route = useRoute() //我们从data中获取值 data.find(v=>v.id === route.params.id)//直接找find,会返回一个对象 //这个时候提示"此条件将始终返回false",因为类型"number"和string|string[]没有重叠 //我们知道他的类型是RouteParams,所以我们要进入源码进行寻找原因了,此时进度条在8分08秒 //我们在源码中找到RouteParams,看到他的类型是RouteParamValue|RouteParamValue[] //RouteParamValue类型是等于string的,数字的话,三个等于号的情况下将永远不会等于字符串。所以我们这里使用Number const item = data.find(v=>v.id === Number(route.params.id))//在data中找我们需要的东西
- 此时需要同步进行改变的部分
//改变前 //<div>品牌:{{ route.params?.name }}</div> //<div>价格:{{ route.params?.price }}</div> //<div>ID:{{ route.params?.id }}</div> //改变后 <div>品牌:{{ item?.name }}</div> //记得要加上问号,这是可选的意思,不然要是没有name岂不是要爆错,所以要是找不到就不要了,给自己留个余地 <div>价格:{{ item?.price }}</div> <div>ID:{{ item?.id }}</div>
//代码块1 const routes:Array<RouteRecordRaw> = [ { path:"/", name:"Login", component:()=> import('../components/login.vue') }, { //动态路由参数 path:"/reg/:id",//注意冒号后面的id,这个就是要对应上的部分 name:"Reg", component:()=> import('../components/reg.vue') } ]
find知识点补充:
find 函数基本格式:let obj=this.list.find(item=>item.code===val)
首先在这里我们要知道的两个基础知识
一、find 是一个查找函数。
二、箭头函数 find(item=>item.code===val)
相当于 find(item){item.code===val}
其中 list
是数组,this.list.find()
是指在 list
数组中找某样东西,item
是 find()
函数的寻找某样东西的根据,也可以说是 id
或者是主键。后面 item.code===val
是查找这样东西的条件,只有这个 item.code
完全等于 val
的时候,才算是找到,才能赋值给 obj
//举例 //定义一个数组,有两条数据 companyOptions: [ { label: '饿了么', value: 0, }, { label: '美团', value: 1, }, ] //需要找到value为1,label为美团的数组 let obj=this.companyOptions.find(item=>item.value===1)
小总结
二者的区别
- query 传参配置的是 path,而 params 传参配置的是 name,在 params 中配置 path 无效
- query 在路由配置不需要设置参数,而 params 必须设置
- query 传递的参数会显示在地址栏中
- params 传参刷新会无效,但是 query 会保存传递过来的值,刷新不变;
- 路由配置
第五章——嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构
在原有基础上的变化
- 我们原本是路由器里面放路由,而嵌套路由就是在路由器里的路由里面继续放路由的一个过程。所以他叫嵌套路由
- 写法上是在路由里面的
children
属性,英文翻译过来就是孩子们的意思,其实也就是子路由(嵌套路由)的意思 - 注意点:
- 你在路由里面继续放路由了,那此时这个二级路由记得要给他们找个容器进行显示
- 你要通过跳转的时候,路径上不能直接写二级路由的path,要先写上一级路由的path然后/二级路由的path。因为他这个寻找逻辑是一层层寻找的,先找到一级路由再继续往下寻找(直接写二级路由的话,在一级路由肯定是找不到的,就会噶了)
children
配置只是另一个路由数组,就像routes
本身一样。因此,你可以根据自己的需要,不断地嵌套视图
const routes: Array<RouteRecordRaw> = [ { path: "/user",//一级路由 component: () => import('../components/footer.vue'), children: [//注意看,嵌套路由的写法是数组里面装对象的形式 { path: "",//嵌套路由1号(也叫做二级路由) name: "Login", component: () => import('../components/login.vue') }, { path: "reg",//嵌套路由二号 name: "Reg", component: () => import('../components/reg.vue') } ] }, ]
Vue3——Router4教程(小满版本)(二)https://developer.aliyun.com/article/1470381