一、to在vue router里扮演啥角色?
做Vue项目时,路由跳转是绕不开的环节,而vue - router里的「to」总在各种跳转场景里出现,不少刚入门的同学会疑惑:这to到底是干啥的?怎么用才能让路由跳转既顺手又不出错?今天咱们就把to的用法、门道拆明白,从基础到实战一次性讲透。
简单说,to是“路由跳转目标”的载体——不管是用声明式的<router - link>组件,还是编程式的router.push()这类方法,to的作用都是告诉vue - router“我要跳转到哪个路由”。
打个比方:你想去商场某家店(目标路由),<router - link>就像“导航指引牌”,to是牌上写的“店铺位置”;router.push()这类方法像“手机导航APP”,to是你在APP里输入的“目的地”,没有to,vue - router根本不知道该往哪跳,所以它是路由跳转的核心配置项。
里的to咋用?
<router - link>是Vue里声明式导航的核心组件(不用写JS逻辑,靠HTML标签实现跳转),它的to属性有两种玩法:
字符串形式(直接写路径)
最基础的用法是把目标路由的路径字符串丢给to,
<router - link to="/home">跳转到首页</router - link> <router - link to="/user/123">跳转到ID为123的用户页</router - link>
这种方式简单直接,但有个问题:如果项目后期调整了路由路径(比如把/user
改成/member
),所有写死路径的地方都得改,维护起来麻烦。
对象形式(灵活配置路由)
为了更灵活,to还支持对象格式,里面能配name
(路由命名)、path
(路径)、params
(动态参数)、query
(查询参数)这些属性,举个栗子:
<router - link :to="{ name: 'UserDetail', // 路由的name(路由配置里定义的) params: { id: 123 }, // 动态参数,对应路由里的/:id query: { tab: 'info' } // 查询参数,会显示在url?后面 }" >跳转到用户详情</router - link>
这里得注意路由配置要和参数对应上,比如路由配置如果是:
{ path: '/user/:id', name: 'UserDetail', component: UserDetail }
那params.id
必须传,否则匹配不到路由;而query
是可选的,用来附加额外信息(比如tab切换标识)。
编程式导航里的to咋玩?
除了声明式的<router - link>,Vue里还有编程式导航(靠JS代码触发跳转),比如this.$router.push()
、this.$router.replace()
、this.$router.go()
这些方法,这里的to
和<router - link>的to逻辑一样,也是字符串或对象形式。
场景:按钮点击跳转
比如页面有个“去关于页”的按钮,点击时用编程式导航:
<button @click="goAbout">去关于页</button>
export default { methods: { goAbout() { // 字符串形式 this.$router.push('/about'); // 对象形式(假设路由name是About) this.$router.push({ name: 'About' }); } } }
带参数的编程式跳转
如果要跳转到“商品详情页”并传商品ID,用对象形式更灵活:
goProductDetail(productId) { this.$router.push({ name: 'ProductDetail', params: { id: productId }, query: { from: 'home' } }); }
路由配置得对应/product/:id
,这样跳转后url会变成/product/100?from = home
,目标组件里可以用this.$route.params.id
和this.$route.query.from
拿到参数。
命名路由的优势
前面提到用name
而不是path
,好处是路由路径变化时,只要name不变,代码不用改,比如路由配置从path: '/product'
改成path: '/goods'
,只要name: 'ProductDetail'
还在,所有用name
跳转的地方都不用动,维护性拉满。
to里传参有啥讲究?
用to传参时,params
和query
是最常用的两种方式,但它们的作用、显示方式、是否必填完全不同,得搞清楚区别:
params:动态路由的“必填项”
params
是给动态路由段传值的(路由配置里带的部分,比如/user/:id
里的:id
),特点是:
- 必须和路由配置的动态段一一对应,否则路由匹配失败(比如少传id会跳404);
- 传参后,参数会嵌入到url路径里(比如
/user/123
),刷新页面参数不会丢(因为在url里); - 如果用
path
配to,传params
会失效!// 错误写法:用path时传params不生效 this.$router.push({ path: '/user', params: { id: 123 } }); // 正确写法:用name + params,或者path直接写全 this.$router.push({ name: 'User', params: { id: 123 } }); this.$router.push('/user/123');
query:附加信息的“可选包”
query
是给路由附加查询参数的(类似url里的?xxx = xxx
),特点是:
- 属于“额外信息”,不传也能跳转,路由配置里不需要提前定义;
- 传参后,参数会跟在url的?后面(比如
/home?tab = news
); - 刷新页面时,query参数默认会保留(因为在url里),但如果是单页应用部署在History模式下,服务器没配置的话可能有问题,不过这是另一个话题了~
目标组件怎么收参?
不管是params
还是query
,目标组件里都得通过this.$route
来拿(注意是$route
不是$router
!$router
是路由实例,用来跳转;$route
是当前路由信息对象,存着参数、路径这些)。
比如在UserDetail组件里:
export default { created() { console.log(this.$route.params.id); // 拿动态参数 console.log(this.$route.query.tab); // 拿查询参数 } }
to和其他路由跳转方式咋区分?
vue - router里跳转方法不少,to
是它们的“目标配置”,但不同方法的跳转逻辑不一样,得分清:
router.push(to):添加新历史记录
最常用的跳转方式,点击跳转后,浏览器历史记录会新增一条,所以点击返回能回到上一页,比如从首页跳详情页,用push
的话,返回能回到首页。
router.replace(to):替换当前历史记录
和push
的区别是,它会替换掉当前的历史记录,比如在支付页完成支付后跳结果页,用replace
的话,用户点返回不会回到支付页(避免重复支付),而是回到更前面的页面。
<router - link>里可以加replace
属性实现同样效果:
<router - link to="/result" replace>跳转到结果页(替换记录)</router - link>
router.go(n):前进/后退历史记录
这个方法里没有to,而是传数字n,比如this.$router.go(-1)
表示后退一页,this.$router.go(1)
表示前进一页,它是操作浏览器历史记录的“前进后退”,和to负责的“指定目标”逻辑不同。
用to时容易踩的坑?
新手用to经常栽跟头,这些常见坑得提前避坑:
“path + params”传参失效
前面讲过,用path
配置to时,传params
是无效的,因为path
和params
是“强绑定”到路由配置的动态段的,只有用name
才能让params
生效。传params必须用name,或者直接在path里写死参数(比如/user/123
)。
动态路由没传参导致404
如果路由配置是/user/:id
,但跳转时没传id
(比如params: { id: undefined }
),vue - router找不到匹配的路由,就会跳404页面(如果配置了的话),所以动态路由的参数必须传!
query参数刷新后消失?
正常情况下,query参数在url里,刷新不会丢,但如果你的项目用了Hash模式(url带#),且服务器没正确配置,或者参数是通过params
传的(但没走动态路由),可能出现刷新丢参,这种情况要么改用query,要么把参数存在Vuex或sessionStorage里。
混淆路由守卫里的to
在路由守卫(比如beforeRouteEnter
、beforeEach
)里,也有个to
参数,这个to
是目标路由对象(包含目标路由的path、name、params、query等),和跳转时用的to(配置项)不是一回事,比如在全局守卫里判断目标路由是否需要权限:
router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !isLogin()) { next('/login'); // 如果目标路由需要权限且没登录,跳登录页 } else { next(); } });
这里的to
是目标路由的信息对象,用来做权限判断很方便。
实战中to的灵活运用场景?
光懂理论不够,看几个实战场景里to咋发挥作用:
多语言路由跳转
项目做多语言时,路由可能带locale
参数(比如/en/user
、/zh/user
),用to的对象形式传params
:
<router - link :to="{ name: 'User', params: { locale: $i18n.locale, id: 123 } }" >User Page</router - link>
路由配置对应/:locale/user/:id
,这样切换语言时,路由能自动带上当前语言标识。
权限控制后动态跳转
用户登录后,根据角色跳不同页面:
handleLogin() { const userRole = this.getUserRole(); // 假设拿到角色是admin或user let target = ''; if (userRole === 'admin') { target = { name: 'AdminDashboard' }; } else { target = { name: 'UserCenter' }; } this.$router.push(target); // 根据角色动态生成to的目标 }
列表项跳详情页(带参)
商品列表页,点击某件商品跳详情页,传商品ID:
<template> <div v - for="product in productList" :key="product.id"> <router - link :to="{ name: 'ProductDetail', params: { id: product.id }, query: { source: 'list' } }" >{{ product.name }}</router - link> </div> </template>
详情页里用this.$route.params.id
拿商品ID,用this.$route.query.source
判断用户是从列表还是其他地方进来的,方便做埋点或页面逻辑区分。
说到底,vue - router里的to就是“告诉路由去哪”的关键配置,不管是声明式还是编程式导航,把to的用法、传参逻辑、避坑点吃透,路由跳转这块就稳了,平时写代码时,多结合场景选对to的形式(字符串还是对象)、用好name和params/query的搭配,维护起来更省心,要是碰到问题,先检查to的配置是否和路由规则匹配,参数有没有传对,基本能解决90%的路由跳转bug~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。