手写简版React-router

手写一个简化版本的 React Router,主要实现其核心功能,包括路由配置、路径匹配和导航。

这个简化版本将包括以下组件和函数:

  1. BrowserRouter

  2. Routes 和 Route

  3. Link

  4. useRoutes

  5. useParams

1. 基本框架和组件

1.1. BrowserRouter

BrowserRouter 组件使用 HTML5 History API,并为应用提供路由上下文。

javascript 复制代码
import React, { useState, useEffect, createContext, useContext } from 'react';

const RouterContext = createContext();

function BrowserRouter({ children }) {
  const [location, setLocation] = useState(window.location.pathname);

  useEffect(() => {
    const handlePopState = () => setLocation(window.location.pathname);
    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, []);

  const navigate = (to) => {
    window.history.pushState({}, '', to);
    setLocation(to);
  };

  return (
    <RouterContext.Provider value={{ location, navigate }}>
      {children}
    </RouterContext.Provider>
  );
}

1.2. Routes 和 Route

Routes 组件遍历所有子路由,并匹配当前路径,Route 组件定义路径和对应的组件。

javascript 复制代码
function Routes({ children }) {
  const { location } = useContext(RouterContext);
  let element;

  React.Children.forEach(children, (child) => {
    if (!element && React.isValidElement(child) && matchPath(child.props.path, location)) {
      element = child;
    }
  });

  return element;
}

function Route({ path, element }) {
  return element;
}

Link 组件用于导航。

javascript 复制代码
function Link({ to, children }) {
  const { navigate } = useContext(RouterContext);

  const handleClick = (event) => {
    event.preventDefault();
    navigate(to);
  };

  return <a href={to} onClick={handleClick}>{children}</a>;
}

1.4. useRoutes

useRoutes 是一个 hook,用于在函数组件中使用路由。

javascript 复制代码
function useRoutes(routes) {
  const { location } = useContext(RouterContext);

  for (let route of routes) {
    if (matchPath(route.path, location)) {
      return route.element;
    }
  }

  return null;
}

1.5. useParams

useParams 是一个 hook,用于获取路径参数。

javascript 复制代码
function useParams() {
  const { location } = useContext(RouterContext);
  const path = location;
  const match = path.match(/\/([^\/]+)\/?/);
  return match ? { id: match[1] } : {};
}

2. 路径匹配函数

matchPath 用于检查路径是否匹配。

javascript 复制代码
function matchPath(pattern, pathname) {
  const regex = new RegExp(`^${pattern.replace(/:\w+/g, '([^/]+)')}$`);
  return regex.test(pathname);
}

3. 示例应用

基础定义完成,我们在 React 中使用一下这个 router 。

javascript 复制代码
import React from 'react';
import ReactDOM from 'react-dom';

function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function User() {
  const { id } = useParams();
  return <h2>User ID: {id}</h2>;
}

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/user/1">User 1</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/user/:id" element={<User />} />
      </Routes>
    </BrowserRouter>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));

这个简化版的 React Router,主要实现其核心功能,包括路由配置、路径匹配和导航。省略了很多边缘情况和优化,从本例中可以窥见 react-router 框架整体实现最核心的思路。

4. 补充资料

相关推荐
ylj_dev3 天前
从 0 构建 AI Workload Platform(九):真实场景、最小控制台与开源发布
go·react·开源项目·工作流·ai agent
星辰徐哥3 天前
打破社媒营销信息差:具身交互智能打造全自动化KOL情报体系
运维·python·自动化·交互·react·数字人
Richown3 天前
Three.js 供应链三维可视化:全球物流轨迹、库存热力图与数字孪生的交互呈现
区块链·react
前端技术官3 天前
Web Components 为什么火不起来?
react·web components·ssr·shadow dom·custom elements
钛态3 天前
Vite 中的 CSS 工程化:从 CSS Modules 到 UnoCSS 的渐进式迁移
前端·vue·react·web
circuitsosk4 天前
智能体任务拆解与执行:基于ReAct+Plan-and-Execute框架的行业Skill构建实录
前端·javascript·python·react.js·react·llm agent·智能体编排
名字还没想好☜7 天前
Next.js 用 cookies()/headers() 读请求信息:动态渲染触发、缓存失效与在 Server Action 里读写 cookie
前端·javascript·缓存·react·next.js·app router
DsirNg7 天前
先守住数据,再下沉交互:RSC 组件分层的实战决策法
react·next.js·app router·前端架构·组件设计·react server components·server actions
递归尽头是星辰8 天前
大模型 Agent 知识体系:Java 开发者视角下的原理、架构与选型边界
react·智能体·spring ai·java 后端·大模型 agent
名字还没想好☜10 天前
Next.js Route Handler 做 SSE 服务端推送:实时进度条、自动重连与什么时候别用 WebSocket
开发语言·javascript·websocket·react·sse·next.js