Vue路由三体法则:query是青铜,params像王者,而props才是隐藏的降维打击!

在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 传值的特点

  1. URL 表现直观 :参数直接嵌入 URL 路径中,作为路径的一部分 。例如,/user/123 ,其中 123 就是传递的参数。这种方式使得 URL 看起来简洁明了,能够清晰地反映出所访问资源的标识,常用于标识特定资源的场景,如用户详情页、文章详情页等。
  2. 参数必填性:在定义了参数的路由中,params 参数通常是必填的(除非在路由配置中做了特殊处理)。如果在导航时没有提供相应的参数,可能会导致路由匹配失败。这也使得它在用于定位特定资源时,保证了资源标识的完整性。
  3. 刷新页面参数不丢失:由于参数是 URL 的一部分,所以在页面刷新时,params 参数不会丢失。这对于需要依赖特定参数来展示页面内容的情况非常有用,比如在用户详情页刷新时,依然能够根据 URL 中的参数加载正确的用户信息。
  4. 参数类型有限:主要适用于传递简单的、与路径紧密相关的数据,如 ID、slug 等。对于复杂的数据结构,使用 params 传值不太方便,因为 URL 的长度和格式有一定限制。

query 传值的特点

  1. 灵活性高 :以查询字符串的形式附加在 URL 后面,例如 /search?keyword=vue 。参数不是路由路径的固定部分,所以即使不传递参数也不会影响路由的匹配。这使得它非常适合传递临时性的、非关键的参数,比如搜索关键词、筛选条件等,这些参数对于路由的基本功能不是必需的,但能进一步细化页面展示的内容。
  2. 可传递复杂数据:理论上可以传递更多类型的数据,只要能序列化为字符串格式。虽然通常用于传递简单值,但如果需要,也可以将 JSON 字符串作为参数传递,在接收端再进行解析。不过,由于 URL 长度限制,传递非常大的数据并不合适。
  3. 参数可选:与 params 不同,query 参数是可选的。应用可以根据实际情况决定是否传递某些 query 参数,这为页面之间的交互提供了更大的灵活性。例如,一个列表页面可能支持多种筛选条件,用户可以选择部分条件进行筛选,此时通过 query 参数传递筛选条件就很方便。
  4. 刷新页面参数不丢失:和 params 一样,刷新页面时 query 参数也不会丢失,因为它们都是 URL 的组成部分。这保证了在页面刷新后,基于这些参数展示的内容能够保持一致。

props 传值的特点

  1. 组件解耦:props 传值将路由参数直接作为组件的 props 传入,使得组件与路由之间的耦合度降低。组件只关注接收到的 props 数据,而不需要关心这些数据是从路由的哪个部分获取的。这提高了组件的复用性,同一个组件可以在不同的路由场景下使用,只要传入合适的 props 即可。
  2. 清晰的数据流:通过 props 传值,数据流向更加清晰。在组件定义中可以明确看到它接收哪些参数,方便理解和维护。特别是在使用对象模式和函数模式时,可以更灵活地组织和处理传入的数据,使代码结构更加清晰。
  3. 增强可读性 :相比于直接在组件内部通过 $route 获取参数,props 传值让组件代码更简洁,可读性更强。例如,在组件模板中可以直接使用 {{ propName }} 来展示数据,而不需要通过 $route.params.propName$route.query.propName 这种相对复杂的方式。
  4. 多种模式适用不同场景 :布尔模式适合快速将 route.params 作为 props 传递;对象模式适合传递固定的、与路由参数无关的数据;函数模式则非常灵活,可以根据 route 对象的参数、查询参数等动态生成 props,满足各种复杂的业务需求。
相关推荐
萌萌哒草头将军5 小时前
😡😡😡早知道有这两个 VueRouter 增强插件,我还加什么班!🚀🚀🚀
前端·vue.js·vue-router
申小兮9 天前
Vue Router(二)
前端·vue.js·vue-router
申小兮9 天前
Vue Router
前端·vue.js·vue-router
谎言西西里24 天前
掌握 Vue Router:构建动态单页应用的导航利器🫡
前端·vue-router
86Eric1 个月前
Vue 使用 vue-router 时,多级嵌套路由缓存问题处理
前端·vue.js·vue-router·vue 路由缓存·多级菜单缓存
小刀飘逸1 个月前
vue-router到底有什么用?(解惑篇)
vue.js·vue-router
belldeep1 个月前
vue3:初学 vue-router 路由配置
前端·javascript·vue.js·vue-router
Aphasia3112 个月前
Vue全家桶之一——Vue Router🧑🏻‍💻
前端·vue-router
剪刀石头布啊2 个月前
自动生成路(以及仿nextjs路由)、并做一个简易Element菜单
前端·vue-router