当前位置:首页 > React

自己实现react router

2026-01-26 21:05:19React

实现基本路由功能

创建一个简单的路由系统需要管理URL变化并渲染对应的组件。可以使用浏览器History API或hash模式。

class Router {
  constructor(routes) {
    this.routes = routes;
    this._loadInitialRoute();
    window.addEventListener('popstate', this._handlePopState.bind(this));
  }

  _loadInitialRoute() {
    const path = window.location.pathname;
    this._handleRouteChange(path);
  }

  _handlePopState() {
    const path = window.location.pathname;
    this._handleRouteChange(path);
  }

  _handleRouteChange(path) {
    const matchedRoute = this.routes.find(route => route.path === path);
    if (matchedRoute) {
      matchedRoute.component();
    } else {
      this.routes.find(route => route.path === '/404').component();
    }
  }

  navigate(path) {
    window.history.pushState({}, '', path);
    this._handleRouteChange(path);
  }
}

实现动态路由匹配

扩展基本路由功能以支持参数化路由和通配符。

自己实现react router

class Router {
  // ...原有代码...

  _matchRoute(path) {
    for (const route of this.routes) {
      const paramNames = [];
      const regexPath = route.path
        .replace(/:(\w+)/g, (_, paramName) => {
          paramNames.push(paramName);
          return '([^\\/]+)';
        })
        .replace(/\*/g, '.*');

      const routeRegex = new RegExp(`^${regexPath}$`);
      const match = path.match(routeRegex);

      if (match) {
        const params = {};
        paramNames.forEach((name, index) => {
          params[name] = match[index + 1];
        });
        return { route, params };
      }
    }
    return null;
  }

  _handleRouteChange(path) {
    const match = this._matchRoute(path);
    if (match) {
      match.route.component(match.params);
    } else {
      this.routes.find(route => route.path === '/404').component();
    }
  }
}

实现路由钩子

添加路由守卫功能,在导航前后执行特定逻辑。

class Router {
  constructor(routes) {
    this.routes = routes;
    this.beforeHooks = [];
    this.afterHooks = [];
    // ...其他初始化代码...
  }

  beforeEach(hook) {
    this.beforeHooks.push(hook);
  }

  afterEach(hook) {
    this.afterHooks.push(hook);
  }

  async navigate(path) {
    const currentPath = window.location.pathname;
    if (path === currentPath) return;

    for (const hook of this.beforeHooks) {
      const shouldContinue = await hook(currentPath, path);
      if (shouldContinue === false) return;
    }

    window.history.pushState({}, '', path);
    this._handleRouteChange(path);

    for (const hook of this.afterHooks) {
      hook(currentPath, path);
    }
  }
}

实现嵌套路由

支持子路由配置和嵌套视图渲染。

自己实现react router

class Router {
  // ...原有代码...

  _handleRouteChange(path, parentElement = null) {
    const match = this._matchRoute(path);
    if (!match) {
      this.routes.find(route => route.path === '/404').component();
      return;
    }

    const { route, params } = match;
    if (route.children) {
      const childPath = path.replace(route.path, '') || '/';
      const childMatch = this._matchNestedRoute(childPath, route.children);

      if (childMatch) {
        const element = document.createElement('div');
        route.component(element, params);
        this._handleRouteChange(childPath, element);
      }
    } else {
      route.component(parentElement, params);
    }
  }

  _matchNestedRoute(path, routes) {
    // 类似_matchRoute的实现,但针对子路由
  }
}

实现Link组件

创建声明式导航组件,避免全页面刷新。

class Link extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.addEventListener('click', this._handleClick.bind(this));
  }

  connectedCallback() {
    const href = this.getAttribute('href');
    const text = this.textContent;
    this.shadowRoot.innerHTML = `
      <style>
        a { text-decoration: none; color: inherit; }
      </style>
      <a href="${href}">${text}</a>
    `;
  }

  _handleClick(event) {
    event.preventDefault();
    const href = this.getAttribute('href');
    window.dispatchEvent(new CustomEvent('router:navigate', { detail: href }));
  }
}

customElements.define('router-link', Link);

集成到React

将自定义路由系统与React组件系统集成。

function withRouter(Component) {
  return function WrappedComponent(props) {
    const [currentPath, setCurrentPath] = useState(window.location.pathname);

    useEffect(() => {
      const handleNavigation = (event) => {
        setCurrentPath(event.detail);
      };

      window.addEventListener('router:navigate', handleNavigation);
      return () => {
        window.removeEventListener('router:navigate', handleNavigation);
      };
    }, []);

    return <Component {...props} currentPath={currentPath} />;
  };
}

function Route({ path, component: Component, currentPath }) {
  const router = useContext(RouterContext);
  const match = router._matchRoute(currentPath);

  if (match && match.route.path === path) {
    return <Component params={match.params} />;
  }
  return null;
}

这个实现涵盖了React Router的核心功能,包括基本路由、动态路由、路由守卫、嵌套路由和声明式导航。可以根据需要进一步扩展功能或优化性能。

标签: reactrouter
分享给朋友:

相关文章

电脑如何安装react

电脑如何安装react

安装 Node.js 和 npm React 项目依赖 Node.js 环境,需先安装 Node.js(自带 npm)。访问 Node.js 官网 下载 LTS 版本,运行安装程序并完成配置。安装后,…

react 如何引入jquery

react 如何引入jquery

安装 jQuery 库 在 React 项目中引入 jQuery 的第一步是安装 jQuery。可以通过 npm 或 yarn 安装: npm install jquery # 或 yarn a…

react如何取消渲染

react如何取消渲染

取消渲染的方法 在React中,取消渲染通常指的是在某些条件下阻止组件渲染或中断正在进行的渲染过程。以下是几种常见的方法: 条件渲染 通过条件判断决定是否渲染组件或部分内容。可以使用if语句或三元运…

如何降低react版本

如何降低react版本

降低 React 项目版本的步骤 检查当前 React 版本 运行以下命令查看项目中安装的 React 当前版本: npm list react 或 yarn list react 修改…

vue router 实现

vue router 实现

Vue Router 实现 Vue Router 是 Vue.js 的官方路由管理器,用于构建单页面应用(SPA)。以下是实现 Vue Router 的关键步骤和配置方法。 安装 Vue Route…

react如何开发组件

react如何开发组件

React 组件开发基础 React 组件分为函数组件和类组件两种形式。函数组件是现代 React 开发的主流方式,结合 Hooks 可以实现完整功能。 函数组件示例: function Gree…