在Vue 3项目开发里,Vue Router是实现页面导航和路由管理的关键工具。而在不同页面(组件)间高效准确地传递数据,更是构建交互式应用不可或缺的环节。本文将深入探讨Vue Router中的三种传值方式,并详细讲解如何使用传入的值。
一、params 传值:路径中的数据纽带
1. 路由参数的配置
在Vue Router的配置文件(一般是router/index.js
)里,我们可以定义带参数的路由。比如,我们要创建一个展示用户详细信息的路由:
javascript
import { createRouter, createWebHistory } from 'vue-router'
import UserDetail from '@/views/UserDetail.vue'
const routes = [{
path: '/user/:userId',
name: 'UserDetail',
component: UserDetail
}]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
这里的:userId
就是我们定义的参数,你可以根据实际需求灵活命名,它会作为路径的一部分,用于标识特定的用户。
2. 参数的传递
我们可以借助router.push
方法或者<router - link>
组件来传递params
参数。
- 使用
router.push
传递参数 : 在组件的<script setup>
中,我们可以这样写:
html
<template>
<button @click="goToUserDetail">查看用户详情</button>
</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goToUserDetail = () => {
const userId = 123
router.push({
name: 'UserDetail',
params: { userId: userId } })
}
</script>
- 使用
<router - link>
传递参数:
html
<template>
<router - link :to="{ name: 'UserDetail', params: { userId: 123 } }">查看用户详情</router - link>
</template>
这样,当用户点击按钮或链接时,就会带着userId
参数跳转到对应的路由。
3. 接收并使用传入的值
在目标组件UserDetail.vue
中,我们通过useRoute
组合式函数来获取params
参数:
html
<template>
<div>
<h2>用户详情</h2>
<p>用户ID:{{ userId }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const userId = route.params.userId
</script>
拿到userId
后,我们可以利用它从后端API获取用户的详细信息,比如:
html
<template>
<div>
<h2>用户详情</h2>
<p v - if="user">用户名:{{ user.name }}</p>
<p v - if="user">用户邮箱:{{ user.email }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
import { ref, onMounted } from 'vue'
import axios from 'axios'
const route = useRoute()
const userId = route.params.userId
const user = ref(null)
onMounted(async () => {
try {
const response = await axios.get(`/api/users/${userId}`)
user.value = response.data
} catch (error) {
console.error('获取用户信息失败', error)
}
})
</script>
params
传值适用于标识特定资源的场景,它让URL看起来简洁明了,并且刷新页面时参数不会丢失。
二、query 传值:查询字符串里的信息传递
1. 参数的传递
query
传值是将参数附加在URL的查询字符串中。同样,我们可以使用router.push
或<router - link>
来传递。
- 使用
router.push
传递query
参数: 假设我们有一个搜索功能,需要传递搜索关键词:
html
<template>
<input v - model="searchKeyword" type="text" placeholder="输入搜索关键词">
<button @click="search">搜索</button>
</template> <script setup>
import { useRouter } from 'vue-router'
import { ref } from 'vue'
const router = useRouter()
const searchKeyword = ref('')
const search = () => {
router.push({
path: '/search',
query: { keyword: searchKeyword.value }
})
}
</script>
- 使用
<router - link>
传递query
参数:
html
<template>
<router - link :to="{ path: '/search', query: { keyword: 'vue' } }">搜索Vue相关内容</router - link>
</template>
此时生成的URL类似/search?keyword = vue
。
2. 接收并使用传入的值
在/search
对应的目标组件中,通过useRoute
获取query
参数:
html
<template>
<div>
<h2>搜索结果</h2>
<p>搜索关键词:{{ keyword }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const keyword = route.query.keyword
</script>
然后可以根据这个关键词进行搜索逻辑,比如调用搜索API:
html
<template>
<div>
<h2>搜索结果</h2>
<ul>
<li v - for="result in searchResults" :key="result.id">{{ result.title }}</li>
</ul>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
import { ref, onMounted } from 'vue'
import axios from 'axios'
const route = useRoute()
const keyword = route.query.keyword
const searchResults = ref([])
onMounted(async () => {
try {
const response = await axios.get('/api/search', {
params: { keyword }
})
searchResults.value = response.data
} catch (error) {
console.error('搜索失败', error) }
})
</script>
query
传值适合传递临时性、非关键的参数,即使不传递参数也不会影响路由匹配,并且刷新页面时参数也不会丢失。
三、props 传值:组件化传参的优雅之道
1. 布尔模式
当props
设置为true
时,route.params
会自动作为组件的props
。 在路由配置文件中:
javascript
import { createRouter, createWebHistory } from 'vue-router'
import ProductDetail from '@/views/ProductDetail.vue'
const routes = [ {
path: '/product/:productId',
name: 'ProductDetail',
component: ProductDetail,
props: true
} ]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在ProductDetail.vue
组件中接收props
:
html
<template>
<div>
<h2>产品详情</h2>
<p>产品ID:{{ productId }}</p>
</div>
</template>
<script setup>
defineProps(['productId'])
</script>
2. 对象模式
props
为对象时,对象中的属性会作为组件的props
,常用于传递固定值。 在路由配置中:
javascript
import { createRouter, createWebHistory } from 'vue-router'
import Promotion from '@/views/Promotion.vue'
const routes = [ {
path: '/promotion',
name: 'Promotion',
component: Promotion,
props: {
title: '限时促销活动',
description: '快来选购,享受超值优惠!'
}
}]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在Promotion.vue
组件中接收props
:
html
<template>
<div>
<h2>{{ title }}</h2>
<p>{{ description }}</p>
</div>
</template>
<script setup>
defineProps(['title', 'description'])
</script>
3. 函数模式
props
为函数时,可根据route
对象动态生成props
。 在路由配置中:
javascript
import { createRouter, createWebHistory } from 'vue-router'
import FilterList from '@/views/FilterList.vue'
const routes = [ {
path: '/filter',
name: 'FilterList',
component: FilterList,
props: route => ({
category: route.query.category,
page: parseInt(route.query.page) || 1
})
}]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在FilterList.vue
组件中接收props
:
html
<template>
<div>
<p>筛选类别:{{ category }}</p>
<p>当前页码:{{ page }}</p>
</div>
</template>
<script setup>
defineProps(['category', 'page'])
</script>
props
传值降低了组件与路由的耦合度,让组件复用性更高,代码结构更清晰。 在实际的Vue 3项目开发中,根据不同的业务场景选择合适的传值方式,能够使应用的架构更加合理,开发更加高效。
四、三种传值方式的各自特点
params 传值的特点
- URL 表现直观 :参数直接嵌入 URL 路径中,作为路径的一部分 。例如,
/user/123
,其中123
就是传递的参数。这种方式使得 URL 看起来简洁明了,能够清晰地反映出所访问资源的标识,常用于标识特定资源的场景,如用户详情页、文章详情页等。 - 参数必填性:在定义了参数的路由中,params 参数通常是必填的(除非在路由配置中做了特殊处理)。如果在导航时没有提供相应的参数,可能会导致路由匹配失败。这也使得它在用于定位特定资源时,保证了资源标识的完整性。
- 刷新页面参数不丢失:由于参数是 URL 的一部分,所以在页面刷新时,params 参数不会丢失。这对于需要依赖特定参数来展示页面内容的情况非常有用,比如在用户详情页刷新时,依然能够根据 URL 中的参数加载正确的用户信息。
- 参数类型有限:主要适用于传递简单的、与路径紧密相关的数据,如 ID、slug 等。对于复杂的数据结构,使用 params 传值不太方便,因为 URL 的长度和格式有一定限制。
query 传值的特点
- 灵活性高 :以查询字符串的形式附加在 URL 后面,例如
/search?keyword=vue
。参数不是路由路径的固定部分,所以即使不传递参数也不会影响路由的匹配。这使得它非常适合传递临时性的、非关键的参数,比如搜索关键词、筛选条件等,这些参数对于路由的基本功能不是必需的,但能进一步细化页面展示的内容。 - 可传递复杂数据:理论上可以传递更多类型的数据,只要能序列化为字符串格式。虽然通常用于传递简单值,但如果需要,也可以将 JSON 字符串作为参数传递,在接收端再进行解析。不过,由于 URL 长度限制,传递非常大的数据并不合适。
- 参数可选:与 params 不同,query 参数是可选的。应用可以根据实际情况决定是否传递某些 query 参数,这为页面之间的交互提供了更大的灵活性。例如,一个列表页面可能支持多种筛选条件,用户可以选择部分条件进行筛选,此时通过 query 参数传递筛选条件就很方便。
- 刷新页面参数不丢失:和 params 一样,刷新页面时 query 参数也不会丢失,因为它们都是 URL 的组成部分。这保证了在页面刷新后,基于这些参数展示的内容能够保持一致。
props 传值的特点
- 组件解耦:props 传值将路由参数直接作为组件的 props 传入,使得组件与路由之间的耦合度降低。组件只关注接收到的 props 数据,而不需要关心这些数据是从路由的哪个部分获取的。这提高了组件的复用性,同一个组件可以在不同的路由场景下使用,只要传入合适的 props 即可。
- 清晰的数据流:通过 props 传值,数据流向更加清晰。在组件定义中可以明确看到它接收哪些参数,方便理解和维护。特别是在使用对象模式和函数模式时,可以更灵活地组织和处理传入的数据,使代码结构更加清晰。
- 增强可读性 :相比于直接在组件内部通过
$route
获取参数,props 传值让组件代码更简洁,可读性更强。例如,在组件模板中可以直接使用{{ propName }}
来展示数据,而不需要通过$route.params.propName
或$route.query.propName
这种相对复杂的方式。 - 多种模式适用不同场景 :布尔模式适合快速将
route.params
作为 props 传递;对象模式适合传递固定的、与路由参数无关的数据;函数模式则非常灵活,可以根据route
对象的参数、查询参数等动态生成 props,满足各种复杂的业务需求。