手写简版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. 补充资料

相关推荐
叫我一声阿雷吧1 天前
JS 入门通关手册(24):Promise:从回调地狱到异步优雅写法
javascript·前端开发·promise·前端面试·异步编程·js进阶·js异步
吐个泡泡v1 天前
AI Agent 核心认知框架详解
react·cot·ai agent·认知框架
~无忧花开~1 天前
React组件与Props完全指南
开发语言·前端·react
yusheng_xyb1 天前
使用TypeScript与React构建高效用户界面
typescript·react·前端开发
胡少侠72 天前
ReAct Agent:手写 Thought-Action-Observe 循环,从工具调用到真正的 Agent
ai·agent·react·rag
胡西风_foxww3 天前
nextjs部署更新,Turbopack 和 Webpack 缓存冲突问题解决
缓存·webpack·react·nextjs·turbopack
叫我一声阿雷吧5 天前
JS 入门通关手册(20):构造函数与原型:JS 面向对象第一课
开发语言·javascript·前端开发·前端面试·构造函数·js进阶·js面向对象
We་ct7 天前
React 更新触发原理详解
开发语言·前端·javascript·react.js·面试·前端框架·react
追光少年33228 天前
支付宝第三方登录集成教程:从申请到实现
前端开发·支付宝·oauth2.0·后端开发·第三方登录·api集成
We་ct8 天前
React Render 与 Commit 阶段详解
前端·react.js·面试·前端框架·react·commit·render