本文作者为奇舞团前端开发工程师
简介
Vue Router 是Vue.js的官方路由。与Vue.js核心深度集成,让用Vue.js构建单页应用(SPA)变得更加简单。对于开发和维护管理后台类的前端项目,页面结构和组合可能非常复杂,所以正确的理解和使用Vue Router就显得尤为重要。
使用
创建
1、在安装好Vue Router依赖后,在App.vue
中引入router-view
,它是渲染的容器
<div id="app">
<router-view></router-view>
</div>
2、创建路由router/index.js
const routes = [
{ path: '/', component: Home},
{ path: '/login', name: 'login', component: Login},
]
const router = createRouter({
history: createWebHistory(),
routes: routes,
})
export default router
3、在main.js
中使用路由
import router from "./router";
const app = createApp(App)
app.use(router)
app.mount('#app')
然后就可以在任意组件中使用this.$router
形式访问它,并且以 this.$route
的形式访问当前路由:
// Home.vue
export default {
computed: {
username() {
// 我们很快就会看到 `params` 是什么
return this.$route.params.username
},
},
methods: {
goToDashboard() {
if (isAuthenticated) {
this.$router.push('/dashboard')
} else {
this.$router.push('/login')
}
},
},
}
嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:
/user/johnny/profile /user/johnny/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
在上层app节点的顶层router-view
下,又包含的组件自己嵌套的router-view
,例如以上的user
模版:
const User = {
template: `
<div class="user">
<h2>User {
{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`,
}
要将组件渲染到这个嵌套的router-view
中,我们需要在路由中配置 children
:
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
下面我们从源码的角度看下页面是如何加载并显示到页面上的
原理
上面基础的使用方法可以看出,主要包含三个步骤:
创建
createRouter
,并在app中use
使用这个路由在模版中使用
router-view
标签导航
push
,跳转页面
从routers声明的数组结构可以看出,声明的路由path
会被注册成路由表指向component
声明的组件,并在push
方法调用时,从路由表查出对应组件并加载。下面看下源码是如何实现这一过程的,Vue Router源码分析版本为4.1.5
创建安装
首先看下createRouter
方法实现:
/**
* Creates a Router instance that can be used by a Vue app.
*
* @param options - {@link RouterOptions}
*/
export function createRouter(options: RouterOptions): Router {
const matcher = createRouterMatcher(options.routes, options)
// ...
function addRoute(
parentOrRoute: RouteRecordName | RouteRecordRaw,
route?: RouteRecordRaw
) {
// ...
}
function getRoutes() {
return matcher.getRoutes().map(routeMatcher => routeMatcher.record)
}
function hasRoute(name: RouteRecordName): boolean {
return !!matcher.getRecordMatcher(name)
}
function push(to: RouteLocationRaw) {
return pushWithRedirect(to)