【Vue2】路由相关的知识点汇总
一、路由的跳转(路由的跳转就两种形式):
- 声明式导航(router-link:务必要有to属性)
- 编程式导航$router.push||replace
编程式导航更好用,以下只讨论编程式导航
- 优点:因为可以书写自己的业务逻辑,更加灵活
- 缺点:
编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误?
注意:编程式导航(push|replace)才会有这种情况的异常,声明式导航是没有这种问题,因为声明式导航内部已经解决这种问题。这种异常,对于程序没有任何影响的。
为什么会出现这种现象:
由于vue-router引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,
下面代码重写:是给push函数,传递相应的成功的回调与失败的回调
重写VueRouter原型对象的push和replace方法
// 先把VueRouter原型对象的方法,保存一份
let originPush = VueRouter.prototype.push
let originReplace = VueRouter.prototype.replace
// 重写push|replace方法,
// 第一个参数:需要跳转的地址(传递那些参数),
// 第二个参数:成功的回调,
// 第三个参数:失败的回调
// 这里使用call||apply都可以修改函数的this指向,注意call传递参数用逗号隔开,apply传递参数用数组
VueRouter.prototype.push = function(location,resolve,reject){
if(resolve && reject){
originPush.call(this,location,resolve,reject)
}else{
originPush.call(this,location,()=>{},()=>{})
}
}
VueRouter.prototype.replace = function(location,resolve,reject){
if(resolve && reject){
originReplace.call(this,location,resolve,reject)
}else{
originReplace.call(this,location,()=>{},()=>{})
}
}
二、路由组件(页面)与非路由组件(组件)
- 路由组件通常存放在 pages || views 文件夹,一般组件(非路由组件)通常存放在components文件夹。
- 2路由组件一般需要在router文件夹中进行注册(使用的即为组件的名字),非路由组件在使用的时候,一般都是以标签的形式使用
- 通过切换,‘隐藏’了的路由组件,默认是被销毁掉的,需要的时候再去挂载
- 每个组件都有组件的$route属性,里面存储着组件的路由消息。
- 整个应用只有一个router,可以通过组件的$router属性获取到
三、两个重要的属性$router和$route
-
$router:路由器对象
router是挂载在根组件上的对象,这是一个全局的对象
<!--在组件中可以通过this.$router来获取路由器对象。-->
this.$router.push(path) 相当于点击<router-link>标签 还可以返回之前的路由
this.$router.replace(path) 用新的路由,把老的路由替换掉,不可以返回之前的路由
this.$router.back(); 返回上一个路由
this.$router.forward(); 返回下一个路由
this.$router.go(-1); 返回上一个路由
this.$router.go(-2); 返回上两个路由
this.$router.go(1); 返回下一个路由
this.$router.go(2); 返回下两个路由
- $route:当前路由信息
route是某一个跳转后的路由对象,是一个局部的对象
<!--在组件中可以通过this.$route来获取路由对象。-->
*this.$route.path string,获取路由的url
*this.$route.params object,获取通过params传递的参数
*this.$route.query object,获取通过查询字符串传递的参数
*this.$route.name string,获取路由配置中的name
*this.$route.meta object,获取当前路由元信息
this.$route.fullPath string,完成解析后的 URL,包含查询参数和 hash 的完整路径。
this.$route.matched array,一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。
this.$route.hash 当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
四、路由传参(区分大小写)
- params参数: 路由中需要占位,使用params传参只能用name来引入路由(不能使用path)
- query参数: 路由不需要占位,使用query传参不限制name或者path引入路由
- 路由组件props:参数复杂起来,起到过滤参数的作用
1.params和query传参
路由配置信息
{
name:'search', //命名路由,编程式路由使用params传参时必须要使用命名路由
path:'/search/:keyword?', //在占位符后面写上一个?来表明可传可不传
component:()=>import('@/pages/Search'),
meta:{showFooter:true},
},
路由跳转传参
toSearch(){
// 编程式路由导航中,对象写法中如果写了params参数配置项中不能写path必须写name(必须提前给url配置name属性),如果写了path则会忽略params
<!-- 对象形式,query参数写法 -->
this.$router.push({
name:'search', // 使用params参数不允许使用path引入路由
// 对应的路由文件中,path:'/search/:keyword?', ,params传参需要提前在路由url中使用:占位符
// 在占位符后面写上一个?来表明可传可不传
params:{searchWord : a}
})
<!-- 对象形式,query参数写法 -->
this.$router.push({
// name:'search',
path:'search', // query参数不限制使用name或path引入路由
query:{searchWord: b}
})
}
使用params参数,页面url不显示参数名称 http://localhost:8080/search/a
获取params参数 this.$route.params.searchWord
使用query参数,页面url显示 http://localhost:8080/search?searchWord=b
获取query参数 this.$route.query.searchWord
2.路由组件props传参
当参数变为复杂,为了更方便的接收参数(起到解耦的作用)。和props配置项一样需要在组件实例身上通过props:['a','b']接收使用。即跳转组件类似形成父子关系进行props传参。
-
布尔模式
如果 props 被设置为 true,route.params所有参数通过props传递给组件。
-
对象模式
如果 props 是一个对象,该对象以键值对的组合通过props传递给组件。当 props 是静态的时候有用。
-
函数模式
你可以创建一个函数返回 props。函数返回的对象以键值对通过props传递给组件,可以params参数、query参数、通过props传递给路由组件。
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail', //二级路由不能加路径
component:Detail,
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
props:{a:1,b:'hello'},
// props的第二种写法,值为对象,若布尔值为真,就会把路由组件收到的所有params参数,以props的形式传给Detail组件
props:true,
// props的第三种写法,值为函数,此写法最强大,此处可以解构赋值并连续解构赋值
props($route){
return {
id:$route.query.id,
title:$route.query.title
}
}
}
]
},
五、路由的嵌套
配置路由规则,使用children配置项
// 创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
name: 'center',
path: '/center',
component: () => import('@/pages/Center'),
meta: { showFooter: true },
// 二级路由组件
children: [
{
path: 'myorder', //二级路由不能加路径/
component: () => import('@/pages/Center/MyOrder'),
},
{
path: 'grouporder', //二级路由不能加路径/
component: () => import('@/pages/Center/GroupOrder'),
},
{
path: '/center', //重定向的时候需要加路径/
redirect: '/center/myorder'
}
]
}
]
})
六、路由元信息meta
路由元信息可以当做一个开关,在路由配置信息中控制控制显示、隐藏 和 登录校验、权限控制。
-
通过路由元meta和v-show来控制组件的显示与隐藏
<Footer v-show="$route.meta.showFooter"></Footer>
{
name: 'home',
path: '/home',
component: () => import('@/pages/Home'),
meta: { showFooter: true } // 路由元控制显示
},
{
name: 'login',
path: '/login',
component: () => import('@/pages/Login'),
meta: { showFooter: false } // 路由元控制隐藏
}
- 通过路由元meta和beforeEach导航守卫来控制路由权限,登录校验
// 路由页配置页面
{
path: '/normal',
name: 'Normal',
component: Normal,
meta: {login_require: false}, // 路由元 登录许可:false 不需要登录许可
},
{
path: '/vip',
name: 'Vip',
component: Vip,
meta: {login_require: true} // 路由元 登录许可:true 需要登录许可
}
// 路由器页面,全局前置守卫控制登录跳转
router.beforeEach((to, from, next) => {
// some找出当前嵌套路径数组中的路由元信息是否包含登录许可
if (to.matched.some(function (item) { // matched为一个数组,当前所有嵌套路径数据
return item.meta.login_require
})) {
next('/login') // 若发现登录许可为true,则调整登录页面
} else
next() // 若发现登录许可为false,则放行
})
七、路由懒加载
路由懒加载无需额外引入路由组件,当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
{
name: 'home',
path: '/home',
component: () => import('@/pages/Home'), // 路由懒加载
meta: { showFooter: true } // 路由元
},
八、 缓存路由组件
- 作用:正常切换组件,组件会销毁。缓存路由让不展示的路由组件保持挂载,不被销毁
- 具体编码:
<!-- keepalive 缓存多个,:include 必须写组件名.,并且包在router-view外 -->
<keep-alive :include="['News', 'Message']">
<router-view></router-view>
</keep-alive>
<!-- 缓存一个路由组件 -->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
路由组件中的两个新的生命周期钩子
router-view组件,如果被包裹在keep-alive里面,所以路径匹配的组件都会被缓存。
如果使用keep-alive组件将会多出两个钩子函数分别为 activated 和 deactivated。
- 作用:路由组件多出两个钩子,用于捕获路由组件的激活状态。
- 具体名字:
- actived 路由组件被激活时触发
- deactived 路由组件失活时触发
一个使用过的生命周期钩子,把真实的dom放入页面后,在调用nextTick函数
$nextTick(){}
组件的缓存问题
-
组件的缓存可以提升用户的体验
比如:登录输入的时候,当切换其他路由再切回来时,还是保留着之前的输入数据。
-
组件的缓存与ajax发送请求带来的冲突问题
一个组件的数据需要实时跟后台数据同步,如果被keep-alive缓存可能就不会发送ajax请求,这样也就导致不会实时的获取最新的数据
-
keep-alive包裹着的router-view组件位置的所有组件都会被缓存
-
有的组件不想被缓存就需要keep-alive的重要属性去处理
keep-alive重要的两个属性
-
include字符串或正则表达式,只有匹配的组件会被缓存。
-
exclude字符串或正则表达式,任何匹配成功的组件都不会被缓存,用的比较多
九、路由工作模式
路由器的两种工作模式
- 对于一个url来说,什么是hash值---#及其后面的内容就是hash值
- hash值不会包含在HTTP请求中,即:hash值不会带给服务器。
- hash模式:
- 地址中永远带着#号,不美观
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
- 兼容性较好
- history模式:
1.地址干净、美观
2.兼容性和hash模式相比略差
3.应用部署上线时需要后端人员支持,解决刷新页面服务端4040的问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现