动态路由匹配和路由参数
动态路由匹配是 Vue Router 的一个强大功能,它允许你创建灵活且可重用的路由。您可以使用参数来捕获 URL 的动态段,而不是为每个可能的值定义特定路由。这在处理具有唯一标识符的资源(如用户配置文件、产品详细信息或博客文章)时特别有用。路由参数使您能够通过减少对硬编码路由的需求来构建更易于维护和可扩展的应用程序。
了解动态路由匹配
动态路由匹配涉及定义具有可更改段的路由。这些段由路由参数表示,路由参数由冒号 (:
) 后跟名称表示。例如, /users/:id
定义一个路由,该路由与任何以 /users/
开头的 URL 匹配,后跟一个将作为 id
参数捕获的动态分段。
基本示例
考虑您希望根据用户 ID 显示用户配置文件的场景。您可以定义如下路由:
js
const routes = [
{ path: '/users/:id', component: UserProfile }
]
在此示例中,:id
是 route 参数。当用户导航到 /users/123
时,将呈现 UserProfile
组件,并且值 123
将作为 id
参数进行访问。
访问路由参数
在 UserProfile
组件中,您可以使用 $route.params
访问 route 参数。
js
<template>
<div>
<h1>User Profile</h1>
<p>User ID: {{ userId }}</p>
</div>
</template>
<script>
export default {
computed: {
userId() {
return this.$route.params.id;
}
}
}
</script>
在此组件中,userId
计算属性从 $route.params
检索 id
参数并将其显示在模板中。
多个路由参数
您可以在单个路由中定义多个路由参数。例如,如果您有一个类似于 /products/:category/:id
的路由,则可以在组件中访问 category
和 id
参数。
js
const routes = [
{ path: '/products/:category/:id', component: ProductDetails }
]
js
<template>
<div>
<h1>Product Details</h1>
<p>Category: {{ category }}</p>
<p>Product ID: {{ productId }}</p>
</div>
</template>
<script>
export default {
computed: {
category() {
return this.$route.params.category;
},
productId() {
return this.$route.params.id;
}
}
}
</script>
在这种情况下,导航到 /products/electronics/456
将呈现 ProductDetails
组件,其中 category
设置为 electronics,id
设置为 456
。
高级路由参数匹配
Vue Router 提供了控制路由参数匹配方式的高级选项。这包括可选参数、正则表达式匹配等。
可选参数
有时,您可能希望 route 参数是可选的。您可以通过在参数名称后添加问号 (?
) 来实现此目的。例如,/search/:query?
使 query
参数可选。
js
const routes = [
{ path: '/search/:query?', component: SearchResults }
]
js
<template>
<div>
<h1>Search Results</h1>
<p v-if="query">Query: {{ query }}</p>
<p v-else>Enter a search query.</p>
</div>
</template>
<script>
export default {
computed: {
query() {
return this.$route.params.query;
}
}
}
</script>
在此示例中,导航到 /search
将呈现不带查询的 SearchResults
组件,而导航到 /search/vue
将呈现查询参数设置为
vue
的组件。
正则表达式匹配
您可以使用正则表达式为路由参数定义更具体的匹配条件。这是通过在参数名称后的括号内添加正则表达式来完成的。例如, /users/:id(\\d+)
仅当 id
参数由一个或多个数字组成时,才会匹配。
js
const routes = [
{ path: '/users/:id(\\d+)', component: UserProfile }
]
此路由将匹配 /users/123
,但不匹配 /users/abc
。
js
<template>
<div>
<h1>User Profile</h1>
<p>User ID: {{ userId }}</p>
</div>
</template>
<script>
export default {
computed: {
userId() {
return this.$route.params.id;
}
},
watch: {
'$route.params.id': {
handler(newId) {
if (!/^\d+$/.test(newId)) {
alert('Invalid User ID');
this.$router.push('/'); // Redirect to home or another appropriate route
}
},
immediate: true // Check on initial load
}
}
}
</script>
在此示例中,组件使用 watch
根据正则表达式验证 id
参数。如果 ID
不是数字,则会显示警报,并重定向用户。
Catch-all 路由
您可以使用 catch-all 路由来匹配与任何其他已定义路由不匹配的任何 URL。这是通过使用星号 (*
) 作为路由路径来完成的。例如,/*
将匹配任何 URL。
js
const routes = [
{ path: '/users/:id', component: UserProfile },
{ path: '/*', component: NotFound }
]
在此示例中,如果用户导航到与 /users/:id
不匹配的 URL,则将呈现 NotFound
组件。
js
<template>
<div>
<h1>404 Not Found</h1>
<p>The requested page could not be found.</p>
</div>
</template>
优先权
定义路由时,定义路由的顺序很重要。Vue Router 按照定义的顺序匹配路由。因此,应在更通用的路由之前定义更具体的路由。
例如,如果您有以下路由:
js
const routes = [
{ path: '/users/admin', component: AdminProfile },
{ path: '/users/:id', component: UserProfile }
]
如果用户导航到 /users/admin
,则将呈现 AdminProfile
组件,因为它是在 /users/:id
路由之前定义的。如果路由以相反的顺序定义,则将改为呈现 UserProfile
组件,并将 id
设置为 admin
。
实际示例和演示
让我们探索一些使用动态路由匹配和路由参数的实际示例。
博客文章示例
考虑一个博客应用程序,您希望在其中根据其独特的 slug 显示单个博客文章。
js
const routes = [
{ path: '/blog/:slug', component: BlogPost }
]
js
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
</div>
</template>
<script>
export default {
data() {
return {
post: {}
};
},
mounted() {
// Simulate fetching the blog post from an API
setTimeout(() => {
this.post = {
title: 'My First Blog Post',
content: 'This is the content of my first blog post.'
};
}, 500);
}
}
</script>
在此示例中,BlogPost
组件根据 slug
参数获取博客文章数据。
电子商务产品示例
在电子商务应用程序中,您可能希望根据产品 ID 显示产品详细信息。
js
const routes = [
{ path: '/products/:id', component: ProductDetails }
]
js
<template>
<div>
<h1>{{ product.name }}</h1>
<p>Price: {{ product.price }}</p>
<p>{{ product.description }}</p>
</div>
</template>
<script>
export default {
data() {
return {
product: {}
};
},
mounted() {
// Simulate fetching the product details from an API
setTimeout(() => {
this.product = {
name: 'Awesome Product',
price: 99.99,
description: 'This is an awesome product.'
};
}, 500);
}
}
</script>
在此示例中,ProductDetails
组件根据 id
参数获取产品详细信息。
带参数的嵌套路由
您还可以将动态路由匹配与嵌套路由一起使用。例如,您可能有一个用于显示用户配置文件的路由和另一个用于显示其设置的路由。
js
const routes = [
{
path: '/users/:userId',
component: UserProfile,
children: [
{
path: 'settings',
component: UserSettings
}
]
}
]
在这种情况下,UserSettings
组件既可以访问父路由中的 userId
参数,也可以访问其自己的路由中定义的任何其他参数。