一、入门
我们在已有的 Vue 项目上加入 Vue Router 时,需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们,下面是个简单的例子
1. HTML
<script src="https://unpkg.com/vue@3"></script><script src="https://unpkg.com/vue-router@4"></script><div id="app"><h1>Hello App!</h1><p><!--使用 router-link 组件进行导航 --><!--通过传递 `to` 来指定链接 --><!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签--><router-link to="/">Go to Home</router-link><router-link to="/about">Go to About</router-link></p><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view></div>
router-link:自定义组件 router-link 来创建链接,而不是使用 a 标签router-view:将显示与 url 对应的组件,可以把它放在任何地方,以适应我们的布局
2. JavaScript
// 1. 定义路由组件.// 也可以从其他文件导入const Home = { template: '<div>Home</div>' }const About = { template: '<div>About</div>' }// 2. 定义一些路由// 每个路由都需要映射到一个组件。// 我们后面再讨论嵌套路由。const routes = [{ path: '/', component: Home },{ path: '/about', component: About },]// 3. 创建路由实例并传递 `routes` 配置// 你可以在这里输入更多的配置,但我们在这里// 暂时保持简单const router = VueRouter.createRouter({// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。history: VueRouter.createWebHashHistory(),routes, // `routes: routes` 的缩写})// 5. 创建并挂载根实例const app = Vue.createApp({})//确保 _use_ 路由实例使//整个应用支持路由。app.use(router)app.mount('#app')// 现在,应用已经启动了!
通过调用 app.use(router),我们可以在任意组件中以 this.$router 的形式访问它,并且以 this.$route 的形式访问当前路由:
// Home.vueexport default {computed: {username() {// 我们很快就会看到 `params` 是什么return this.$route.params.username},},methods: {goToDashboard() {if (isAuthenticated) {this.$router.push('/dashboard')} else {this.$router.push('/login')}},},}
要在 setup 函数访问路由,需要调用 useRouter 或 useRoute 函数,在 Composition API 中可以了解更多信息
二、动态路由匹配
1. 带参数的动态路由匹配规则
用法如下
const User = {template: '<div>User</div>',}// 这些都会传递给 `createRouter`const routes = [// 动态字段以冒号开始{ path: '/users/:id', component: User },]
- 像
/users/johnny和/users/jolyne这样的 URL 都会映射到同一个路由
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID:
const User = {template: '<div>User {{ $route.params.id }}</div>',}
可以在同一个路由中设置有多个 路径参数,它们会映射到 $route.params 上的相应字段
| 匹配模式 | 匹配路径 | $route.params |
|---|---|---|
| /users/:username | /users/eduardo | { username: 'eduardo' } |
| /users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
除了 $route.params 之外,$route 对象还公开了其他有用的信息,如 $route.query(如果 URL 中存在参数)、$route.hash 等。
2. 响应路由参数的变化
使用带有参数的路由时需要注意的是,当用户从 /users/johnny 导航到 /users/jolyne 时,相同的组件实例将被重复使用。
因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。
不过,这也意味着组件的生命周期钩子不会被调用。
要对同一个组件中参数的变化做出响应的话,你可以简单地 watch $route 对象上的任意属性,在这个场景中,就是 $route.params:
const User = {template: '...',created() {this.$watch(() => this.$route.params,(toParams, previousParams) => {// 对路由变化做出响应...})},}
或者,使用 beforeRouteUpdate 导航守卫,它也可以取消导航:
const User = {template: '...',async beforeRouteUpdate(to, from) {// 对路由变化做出响应...this.userData = await fetchUser(to.params.id)},}
3. 捕获所有路由或 404 Not found 路由
常规参数只匹配 url 片段之间的字符,用 / 分隔。如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :
const routes = [// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },// 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下{ path: '/user-:afterUser(.*)', component: UserGeneric },]
在这个特定的场景中,我们在括号之间使用了自定义正则表达式,并将 pathMatch 参数标记为可选可重复。这样做是为了让我们在需要的时候,可以通过将 path 拆分成一个数组,直接导航到路由:
this.$router.push({name: 'NotFound',params: { pathMatch: this.$route.path.split('/') },})
4. 高级匹配模式
Vue Router 使用自己的路径匹配语法,其灵感来自于 express,因此它支持许多高级匹配模式,如可选的参数,零或多个 / 一个或多个,甚至自定义的正则匹配规则。请查看高级匹配文档来探索它们。
