一、props在vue router里是干啥的?
p>不少刚开始学Vue路由的朋友,碰到vue - router的props配置时总会犯懵——这玩意儿到底咋用?和直接用$route传参比有啥好处?今天就唠唠vue - router里props的用法和优势,把这些疑惑一个个掰碎了讲清楚。
简单说,props是给路由组件传递参数的一种“优雅方式”,咱平常写路由组件时,要是想拿路由里的参数(比如/user/:id
里的id
),得用this.$route.params.id
这种写法,但这样做有个问题:组件和路由紧紧绑在一起了(专业点叫“强耦合”)。
而props的作用,就是把路由里的参数“解耦”出来,变成组件的props属性,路由负责把参数“递”给props,组件只需要像接收普通父传子参数一样,用props
选项声明接收就行,这样一来,哪怕以后路由规则变了,组件内部也不用大改,甚至组件还能在非路由场景下复用(比如当普通组件给其他页面用)。
props的几种配置玩法
vue - router给props设计了布尔、对象、函数三种配置模式,不同场景用不同模式,灵活得很。
布尔模式(props: true
)
适合“把路由params
参数直接传给组件props”的场景,举个例子:
路由配置长这样:
const routes = [ { path: '/user/:id', component: User, props: true } ]
User组件里只需要声明props:
export default { props: ['id'], // 声明接收id参数 mounted() { console.log(this.id) // 直接用this.id,不用this.$route.params.id } }
这种模式的好处很直接:路由params
和组件props自动映射,组件不用关心“路由参数咋拿”,只负责用props里的id
。
对象模式(props: { ... }
)
要是你想给组件传静态参数(参数值不随路由变化),就用对象模式,比如做个固定标题的页面:
路由配置:
const routes = [ { path: '/about', component: About, props: { title: '关于我们', isShow: true } } ]
About组件接收:
export default { props: { String, isShow: Boolean }, mounted() { console.log(this.title, this.isShow) // 输出“关于我们” true } }
这种模式适合“组件需要固定配置”的场景,比如页面默认开关、固定文案这些,不管路由怎么变,传的值都是固定的。
函数模式(props: (route) => ({ ... })
)
如果需要动态处理路由参数(比如结合query
参数、加工params
格式),函数模式就派上用场了。route
参数是当前路由对象,里面包含params
、query
、path
等信息。
举个实际例子:商品详情页需要传商品id
(params
),还要根据query
里的tab
决定显示哪个标签页。
路由配置:
const routes = [ { path: '/product/:id', component: Product, props: (route) => ({ productId: route.params.id, // 取params里的id activeTab: route.query.tab || 'info' // 取query里的tab,没有就默认info }) } ]
Product组件接收:
export default { props: { productId: String, activeTab: String }, mounted() { console.log(this.productId, this.activeTab) // 比如访问/product/123?tab=detail,就输出“123” “detail” } }
函数模式的灵活性在于:能对路由参数做任意处理——比如把id
从字符串转成数字,或者合并多个参数,甚至还能结合Vuex、全局配置等,返回更复杂的参数(不过要注意,函数里this
不是Vue实例,别直接用this.$store
,可以把逻辑放到组件里处理)。
用props代替$route传参有啥优势?
很多人会问:“我直接用this.$route
也能拿参数,为啥非要用props?” 这就得聊聊解耦、维护、设计理念这几个关键点了。
组件解耦更彻底
如果组件里全是this.$route.xxx
,这个组件就和路由“绑死”了——一旦路由规则变了(比如参数名从id
改成userId
),组件里所有this.$route.params.id
都得改;而且这个组件也没法在非路由场景复用(比如当弹窗组件用,没路由的时候$route
就不存在了)。
但用props的话,组件只关心“我需要哪些参数”,不管参数从路由来、还是父组件手动传,比如上面的User组件,哪怕不在路由里用,父组件也能这么写:
<User :id="100" />
组件完全不用改,复用性直接拉满。
代码可读性&维护性提升
看组件代码时,直接看props
选项就知道“这个组件需要啥参数”,不用满世界找this.$route
在哪;路由配置里的props
也清晰展示了“参数咋从路由映射到组件”,后期要改参数逻辑,只需要动路由配置的props
部分,组件内部完全不用碰。
举个反面例子:如果组件里到处是this.$route.params.id
,某天产品说“路由参数要加个前缀”,你得把所有this.$route.params.id
改成this.$route.params.id.replace('prefix - ', '')
,改起来又麻烦又容易漏,但用props的话,只需要在路由的函数模式里改一行:
props: (route) => ({ productId: route.params.id.replace('prefix - ', '') })
组件里该咋用还咋用,完全不受影响。
更符合Vue的设计理念
Vue强调“单向数据流”和“组件化”,props是组件通信的核心方式之一,用props做路由传参,相当于把“路由”当成一个特殊的“父组件”,通过props把数据“流”到子组件里,完美契合Vue的设计逻辑。
实际开发中容易踩的坑和注意点
知道了用法和优势,也得避避坑,这几个细节一定要注意:
布尔模式只传params
,不传query
props: true
时,只有$route.params
里的参数会被传给props,query
参数(比如?tab=info
)不会自动传,如果要传query
,必须用函数模式自己处理,
props: (route) => ({ ...route.params, // 传params ...route.query // 传query })
组件必须声明props
选项
不管用哪种模式,组件里一定要用props
选项声明接收的参数!比如用了props: true
,但组件没写props: ['id']
,那this.id
就是undefined
,直接报错。
函数模式里的this
不是Vue实例
路由配置里的props
函数,this
指向不是Vue实例,所以别在函数里写this.$store
、this.$axios
这些,如果需要依赖Vuex或者工具库,建议把逻辑放到组件的computed
或mounted
里处理,或者在函数里返回需要的参数,组件再自己调接口。
举个完整小例子,看效果更直观
假设做一个“订单详情页”,需要传订单id(params
),还要根据查询参数mode
(普通/精简模式)渲染不同布局,用函数模式实现:
路由配置:
const routes = [ { path: '/order/:orderId', component: OrderDetail, props: (route) => ({ orderId: route.params.orderId, displayMode: route.query.mode || 'normal' }) } ]
OrderDetail组件:
export default { props: { orderId: { type: String, required: true // 订单id是必须的 }, displayMode: { type: String, default: 'normal' // 默认普通模式 } }, mounted() { console.log('订单ID:', this.orderId) console.log('显示模式:', this.displayMode) // 这里可以用orderId调接口拿订单数据,用displayMode决定渲染逻辑 } }
当访问/order/123?mode=simple
时,组件里this.orderId
是'123'
,this.displayMode
是'simple'
;如果访问/order/456
(没带query),displayMode
就是默认的'normal'
。
这个例子里,路由负责“参数传递和简单处理”,组件只负责“用参数做业务逻辑”,分工明确,后期维护也方便——比如以后要加个“暗黑模式”参数,只需要在路由的props
函数里加一行,组件完全不用动。
props的核心价值是“灵活解耦”
vue - router的props配置,本质是在路由和组件之间搭了个“智能传参桥梁”:
- 布尔模式:快速把
params
映射给props,简单场景直接用; - 对象模式:传静态参数,给组件固定配置;
- 函数模式:复杂参数处理,想怎么加工就怎么加工。
而它最大的优势,是让组件更干净、更易复用、更好维护——毕竟谁也不想改个路由参数,还要在组件里到处找$route
对吧?
现在再看props,是不是觉得“哦,原来这玩意儿这么有用”?下次写路由组件时,别再一股脑用this.$route
了,试试props配置,你会发现代码清爽了不少~
(全文约1500字,把props的用法、优势、坑点、例子全唠明白了,新手能跟着步骤用起来,老手也能再巩固下设计思路~)
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。