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

相关推荐
前端不太难2 小时前
Navigation State 与页面内存泄漏的隐性关系
前端·ui·react
weibkreuz4 小时前
React开发者工具的下载及安装@4
前端·javascript·react
许泽宇的技术分享1 天前
当AI学会“画“界面:A2UI如何让智能体拥有UI表达能力
人工智能·生成式ai·前端开发·用户界面·a2ui
大模型教程.2 天前
收藏级教程:ReAct模式详解,让大模型从回答问题到解决问题
前端·人工智能·机器学习·前端框架·大模型·产品经理·react
阿里巴啦3 天前
用React+Three.js 做 3D Web版搭建三维交互场景:模型的可视化摆放与轻量交互
前端·react·three.js·模型可视化·web三维·web三维交互场景
Swift社区4 天前
RN 项目中“页面存在 ≠ 页面可见”会导致哪些隐藏 Bug?
react native·bug·react
蜗牛攻城狮4 天前
PostCSS 详解、最佳实践及其与 Less/SCSS 的关系
less·前端开发·postcss·scss
_OP_CHEN5 天前
【从零开始的Qt开发指南】(十一)Qt常用控件之多元素控件与容器类控件深度解析
开发语言·qt·前端开发·多元素控件·gui开发·qt常用控件·容器类控件
沛沛老爹5 天前
Web开发者快速上手AI Agent:基于提示工程的旅游攻略系统实战
前端·人工智能·ai·agent·react·旅游攻略
旧梦星轨5 天前
掌握 Vite 环境配置:从 .env 文件到运行模式的完整实践
前端·前端框架·node.js·vue·react