面试题:如何自主设计实现一个 Vue 路由系统?

设计一个 Vue 路由系统需要实现以下核心功能:

  1. 路由映射:将 URL 路径映射到对应的组件。
  2. 动态路由:支持动态路径参数(如 /user/:id)。
  3. 路由切换:监听 URL 变化,动态渲染对应的组件。
  4. 导航守卫:在路由切换前后执行钩子函数。
  5. 嵌套路由:支持嵌套的路由配置。

以下是一个简化版的 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 路由系统,核心功能包括:

  1. 路由映射:将 URL 路径映射到对应的组件。
  2. 动态路由:支持动态路径参数。
  3. 路由切换:监听 URL 变化,动态渲染组件。
  4. 导航守卫:在路由切换前后执行钩子函数。
  5. 嵌套路由:支持嵌套的路由配置。

这个简化版的路由系统可以帮助理解 Vue Router 的核心原理,但在实际项目中,建议直接使用 Vue Router,因为它提供了更完善的功能和更好的性能优化。

THE END
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容