# vue-router 原理
单页面的话都是监听URL改变UI 两种方式 hash 和 history
VueRouter核心是,通过Vue.use注册插件,在插件的install方法中获取用户配置的router对象。当浏览器地址发生变化的时候,根据router对象匹配相应路由,获取组件,并将组件渲染到视图上。
- url改变
- 触发事件监听(hash 和 history 的监听不同)
- 改变vue-router中的current变量
- 监视current变量的监视者
- 获取新的组件
- render
vue-router
是 Vue.js 的官方路由管理器,用于在单页面应用(SPA)中实现客户端路由。它的核心原理包括以下几个方面:
Vue组件与路由的映射:
vue-router
通过配置文件将路径映射到 Vue 组件。每当 URL 发生变化时,vue-router
会根据当前路径动态渲染相应的组件。
路由表配置:
- 路由表是一个对象数组,每个对象描述了路径和对应的组件。
- 例如:
const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ]; const router = new VueRouter({ routes });
路由模式:
vue-router
支持两种路由模式:hash
和history
。hash
模式:使用 URL 的 hash (#
) 部分来模拟完整的 URL,当 URL 的 hash 部分发生变化时,页面不会重新加载。history
模式:利用 HTML5 History API 使 URL 看起来更“干净”(没有#
号),但需要服务器配置支持,因为刷新页面时会向服务器发出请求。
导航守卫(Navigation Guards):
vue-router
提供了多种导航守卫,用于在导航触发时执行特定逻辑。- 全局守卫:
router.beforeEach
、router.afterEach
。 - 路由独享守卫:在路由配置中使用
beforeEnter
。 - 组件内守卫:在组件内使用
beforeRouteEnter
、beforeRouteUpdate
、beforeRouteLeave
。
- 全局守卫:
动态路由匹配:
vue-router
支持动态路由匹配,可以在路径中使用参数。- 例如:
/user/:id
,其中:id
是一个动态参数,可以通过this.$route.params.id
访问。
路由懒加载:
- 为了优化性能,
vue-router
支持懒加载组件。即在需要时才加载对应的组件。 - 例如:
const routes = [ { path: '/about', component: () => import('./components/About.vue') } ];
- 为了优化性能,
# Vue Router 工作流程
初始化:
- 创建
VueRouter
实例并传入路由配置。 - 在 Vue 实例中通过
Vue.use(VueRouter)
安装路由插件。 - 挂载到 Vue 实例上:
new Vue({ router, render: h => h(App) }).$mount('#app');
- 创建
路径变化监听:
- 根据选择的路由模式(
hash
或history
),vue-router
会监听 URL 的变化。 - 在
hash
模式下,监听hashchange
事件。 - 在
history
模式下,监听popstate
事件。
- 根据选择的路由模式(
路由匹配:
- 当路径变化时,
vue-router
会遍历路由表,找到匹配的路由规则。 - 如果找到匹配的路由,会加载对应的组件并进行渲染。
- 当路径变化时,
导航守卫执行:
- 在路径变化后,
vue-router
会依次执行导航守卫,从而允许或阻止导航。
- 在路径变化后,
组件渲染:
- 最终,
vue-router
将匹配到的组件渲染到<router-view>
中。
- 最终,
# 简化实现
以下是一个简化版的 vue-router
实现示例:
class VueRouter {
constructor(options) {
this.routes = options.routes;
this.mode = options.mode || 'hash';
this.current = '/';
this.init();
}
init() {
if (this.mode === 'hash') {
window.addEventListener('hashchange', () => {
this.current = window.location.hash.slice(1) || '/';
});
} else {
window.addEventListener('popstate', () => {
this.current = window.location.pathname || '/';
});
}
}
match(path) {
return this.routes.find(route => route.path === path);
}
}
// 使用示例
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];
const router = new VueRouter({ routes });
new Vue({
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent() {
const match = router.match(this.currentRoute);
return match ? match.component : NotFound;
}
},
render(h) {
return h(this.ViewComponent);
}
}).$mount('#app');
这个示例展示了 vue-router
的基本原理,简化了实际实现中的许多细节,比如导航守卫、动态路由等。完整的 vue-router
功能更多,代码更加复杂,但核心思想一致。