设计一个 Vue 路由系统需要实现以下核心功能:
- 路由映射:将 URL 路径映射到对应的组件。
- 动态路由:支持动态路径参数(如
/user/:id
)。 - 路由切换:监听 URL 变化,动态渲染对应的组件。
- 导航守卫:在路由切换前后执行钩子函数。
- 嵌套路由:支持嵌套的路由配置。
以下是一个简化版的 Vue 路由系统的实现思路和代码示例。
1. 路由映射
定义一个路由表,将路径映射到对应的组件。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User },
];
2. 动态路由
支持动态路径参数,并通过 props
将参数传递给组件。
const routes = [
{ path: '/user/:id', component: User, props: true },
];
3. 路由切换
监听 URL 变化,动态渲染对应的组件。
3.1 创建路由实例
class Router {
constructor(routes) {
this.routes = routes;
this.currentRoute = null;
this.init();
}
init() {
window.addEventListener('popstate', () => this.handleRouteChange());
this.handleRouteChange();
}
handleRouteChange() {
const path = window.location.pathname;
const route = this.routes.find(route => this.matchRoute(route, path));
if (route) {
this.currentRoute = route;
this.render();
}
}
matchRoute(route, path) {
const routeParts = route.path.split('/');
const pathParts = path.split('/');
if (routeParts.length !== pathParts.length) return false;
for (let i = 0; i < routeParts.length; i++) {
if (routeParts[i].startsWith(':')) continue;
if (routeParts[i] !== pathParts[i]) return false;
}
return true;
}
render() {
const component = this.currentRoute.component;
const props = this.getRouteProps(this.currentRoute, window.location.pathname);
new Vue({
el: '#app',
render: h => h(component, { props }),
});
}
getRouteProps(route, path) {
if (!route.props) return {};
const routeParts = route.path.split('/');
const pathParts = path.split('/');
const props = {};
for (let i = 0; i < routeParts.length; i++) {
if (routeParts[i].startsWith(':')) {
const key = routeParts[i].slice(1);
props[key] = pathParts[i];
}
}
return props;
}
push(path) {
window.history.pushState({}, '', path);
this.handleRouteChange();
}
replace(path) {
window.history.replaceState({}, '', path);
this.handleRouteChange();
}
}
3.2 使用路由实例
const router = new Router(routes);
// 在组件中使用
new Vue({
el: '#app',
methods: {
navigateTo(path) {
router.push(path);
},
},
});
4. 导航守卫
在路由切换前后执行钩子函数。
4.1 定义导航守卫
class Router {
constructor(routes) {
this.routes = routes;
this.currentRoute = null;
this.beforeEachHooks = [];
this.afterEachHooks = [];
this.init();
}
beforeEach(hook) {
this.beforeEachHooks.push(hook);
}
afterEach(hook) {
this.afterEachHooks.push(hook);
}
async handleRouteChange() {
const path = window.location.pathname;
const route = this.routes.find(route => this.matchRoute(route, path));
if (route) {
for (const hook of this.beforeEachHooks) {
await hook(route, this.currentRoute);
}
this.currentRoute = route;
this.render();
for (const hook of this.afterEachHooks) {
await hook(route, this.currentRoute);
}
}
}
}
4.2 使用导航守卫
router.beforeEach((to, from) => {
console.log(`Navigating from ${from ? from.path : 'none'} to ${to.path}`);
});
router.afterEach((to, from) => {
console.log(`Navigated from ${from ? from.path : 'none'} to ${to.path}`);
});
5. 嵌套路由
支持嵌套的路由配置。
5.1 定义嵌套路由
const routes = [
{
path: '/',
component: Home,
children: [
{ path: 'profile', component: Profile },
{ path: 'settings', component: Settings },
],
},
];
5.2 渲染嵌套路由
class Router {
render() {
const component = this.currentRoute.component;
const props = this.getRouteProps(this.currentRoute, window.location.pathname);
const children = this.currentRoute.children || [];
const childRoutes = children.map(child => ({
path: child.path,
component: child.component,
}));
new Vue({
el: '#app',
render: h => h(component, { props }, [
childRoutes.map(child => h('router-view', { attrs: { path: child.path } })),
]),
});
}
}
总结
通过以上步骤,可以实现一个简化版的 Vue 路由系统,核心功能包括:
- 路由映射:将 URL 路径映射到对应的组件。
- 动态路由:支持动态路径参数。
- 路由切换:监听 URL 变化,动态渲染组件。
- 导航守卫:在路由切换前后执行钩子函数。
- 嵌套路由:支持嵌套的路由配置。
这个简化版的路由系统可以帮助理解 Vue Router 的核心原理,但在实际项目中,建议直接使用 Vue Router,因为它提供了更完善的功能和更好的性能优化。
THE END
暂无评论内容