React 第六十四节Router中HashRouter的使用详细介绍及案例分析

发布于:2025-06-26 ⋅ 阅读:(17) ⋅ 点赞:(0)

前言

HashRouterReact Router 提供的一种路由实现方案,它使用 URL 的 hash 部分# 后面的内容)来实现客户端路由功能。

一、HashRouter 的核心用途

  1. 客户端路由:在不刷新页面的情况下管理应用导航
  2. 兼容性:支持不支持 HTML5 History API 的旧浏览器
  3. 静态服务器支持:不需要服务器配置,适合静态托管环境
  4. 路由隔离:hash 部分不会发送到服务器,完全由客户端处理
  5. 部署简单:无需服务器重定向配置

二、HashRouter 与 BrowserRouter 的主要区别

在这里插入图片描述

三、HashRouter实现原理

HashRouter 利用 URL 的 hash 部分window.location.hash)来存储路由信息:

  1. 改变 hash 不会触发页面刷新
  2. 监听 hashchange 事件来响应路由变化
  3. 通过 window.location.hash 获取当前路由状态

四、HashRouter完整代码示例

import React, { useState } from 'react';
import { HashRouter, Routes, Route, Link, NavLink, useNavigate, useParams, useLocation } from 'react-router-dom';

// 页面组件
const Home = () => (
  <div className="page home">
    <h2>🏠 欢迎来到首页</h2>
    <p>这是一个使用 HashRouter 的 React 应用示例</p>
    <div className="features">
      <div className="feature-card">
        <h3>兼容性强</h3>
        <p>支持所有浏览器,包括旧版IE</p>
      </div>
      <div className="feature-card">
        <h3>部署简单</h3>
        <p>不需要服务器配置,适合静态托管</p>
      </div>
      <div className="feature-card">
        <h3>路由隔离</h3>
        <p>hash部分不会发送到服务器</p>
      </div>
    </div>
  </div>
);

const About = () => (
  <div className="page about">
    <h2>📝 关于我们</h2>
    <p>我们是一个专注于前端技术的团队,致力于提供最佳用户体验</p>
    <div className="team">
      <div className="member">
        <div className="avatar">👨‍💻</div>
        <h3>张三</h3>
        <p>前端架构师</p>
      </div>
      <div className="member">
        <div className="avatar">👩‍🎨</div>
        <h3>李四</h3>
        <p>UI设计师</p>
      </div>
      <div className="member">
        <div className="avatar">👨‍🏫</div>
        <h3>王五</h3>
        <p>技术顾问</p>
      </div>
    </div>
  </div>
);

// 产品列表页
const Products = () => {
  const products = [
    { id: 1, name: 'React 教程', price: 99 },
    { id: 2, name: 'JavaScript 高级编程', price: 129 },
    { id: 3, name: 'CSS 大师课', price: 89 },
  ];
  
  return (
    <div className="page products">
      <h2>🛒 产品列表</h2>
      <div className="product-grid">
        {products.map(product => (
          <div key={product.id} className="product-card">
            <div className="product-image">📚</div>
            <h3>{product.name}</h3>
            <p>¥{product.price}</p>
            <Link to={`/products/${product.id}`} className="btn">
              查看详情
            </Link>
          </div>
        ))}
      </div>
    </div>
  );
};

// 产品详情页(动态路由)
const ProductDetail = () => {
  const { id } = useParams();
  const location = useLocation();
  
  // 模拟产品数据
  const products = {
    1: { name: 'React 教程', description: '深入学习React框架的最佳指南', price: 99 },
    2: { name: 'JavaScript 高级编程', description: '掌握JavaScript高级技巧', price: 129 },
    3: { name: 'CSS 大师课', description: '成为CSS专家的必修课程', price: 89 },
  };
  
  const product = products[id] || {
    name: '未知产品',
    description: '该产品不存在',
    price: 0
  };
  
  return (
    <div className="page product-detail">
      <h2>🔍 产品详情</h2>
      <div className="product-info">
        <div className="product-header">
          <h3>{product.name}</h3>
          <p className="price">¥{product.price}</p>
        </div>
        <p>{product.description}</p>
        <p className="meta">产品ID: {id} | 当前路径: {location.pathname}</p>
        <Link to="/products" className="btn">
          ← 返回产品列表
        </Link>
      </div>
    </div>
  );
};

// 登录页(演示编程式导航)
const Login = () => {
  const navigate = useNavigate();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  
  const handleLogin = (e) => {
    e.preventDefault();
    // 模拟登录逻辑
    if (username && password) {
      // 登录成功后导航到仪表盘
      navigate('/dashboard');
    }
  };
  
  return (
    <div className="page login">
      <h2>🔑 用户登录</h2>
      <form onSubmit={handleLogin}>
        <div className="form-group">
          <label>用户名</label>
          <input 
            type="text" 
            value={username} 
            onChange={(e) => setUsername(e.target.value)}
            placeholder="输入用户名"
          />
        </div>
        <div className="form-group">
          <label>密码</label>
          <input 
            type="password" 
            value={password} 
            onChange={(e) => setPassword(e.target.value)}
            placeholder="输入密码"
          />
        </div>
        <button type="submit" className="btn">登录</button>
      </form>
    </div>
  );
};

// 仪表盘页(受保护路由)
const Dashboard = () => {
  return (
    <div className="page dashboard">
      <h2>📊 用户仪表盘</h2>
      <p>欢迎访问您的个人仪表盘!</p>
      <div className="stats">
        <div className="stat-card">
          <h3>28</h3>
          <p>已完成课程</p>
        </div>
        <div className="stat-card">
          <h3>12</h3>
          <p>进行中课程</p>
        </div>
        <div className="stat-card">
          <h3>5</h3>
          <p>收藏课程</p>
        </div>
      </div>
    </div>
  );
};

// 404 页面
const NotFound = () => (
  <div className="page not-found">
    <h2>🔍 404 - 页面未找到</h2>
    <p>抱歉,您访问的页面不存在</p>
    <Link to="/" className="btn">
      返回首页
    </Link>
  </div>
);

// 导航组件
const Navigation = () => {
  const location = useLocation();
  
  return (
    <nav>
      <div className="logo">
        <Link to="/">HashRouter示例</Link>
      </div>
      <div className="nav-links">
        <NavLink to="/" end className={({isActive}) => isActive ? 'active' : ''}>
          首页
        </NavLink>
        <NavLink to="/about" className={({isActive}) => isActive ? 'active' : ''}>
          关于
        </NavLink>
        <NavLink to="/products" className={({isActive}) => isActive ? 'active' : ''}>
          产品
        </NavLink>
        <NavLink to="/login" className={({isActive}) => isActive ? 'active' : ''}>
          登录
        </NavLink>
      </div>
      <div className="location-info">
        当前路径: <code>{location.pathname}</code>
      </div>
    </nav>
  );
};

// 主应用组件
function App() {
  return (
    <HashRouter>
      <div className="app">
        <Navigation />
        
        <main>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/products" element={<Products />} />
            <Route path="/products/:id" element={<ProductDetail />} />
            <Route path="/login" element={<Login />} />
            <Route path="/dashboard" element={<Dashboard />} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </main>
        
        <footer>
          <p>使用 React Router HashRouter 实现 | 当前URL: {window.location.href}</p>
          <div className="hash-info">
            <strong>Hash部分:</strong> {window.location.hash}
          </div>
        </footer>
      </div>
    </HashRouter>
  );
}

五、HashRouter 关键特性详解

5.1、 基本路由配置

<HashRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
    <Route path="/products" element={<Products />} />
    <Route path="*" element={<NotFound />} />
  </Routes>
</HashRouter>

5.2、 动态路由参数

<Route path="/products/:id" element={<ProductDetail />} />

// 在组件中获取参数
const ProductDetail = () => {
  const { id } = useParams();
  // ...
}

5.3、 编程式导航

const Login = () => {
  const navigate = useNavigate();
  
  const handleLogin = () => {
    // 登录逻辑...
    navigate('/dashboard'); // 跳转到仪表盘
  };
  
  // ...
}

5.4、 导航链接

// 普通链接
<Link to="/about">关于我们</Link>

// 活动链接样式
<NavLink to="/products" className={({isActive}) => 
  isActive ? 'active' : ''
}>
  产品
</NavLink>

5.5、 获取位置信息

const location = useLocation();
console.log(location.pathname); // 当前路径

六、使用场景建议

  1. 静态网站托管GitHub Pages、Netlify、Vercel 等静态托管服务
  2. 旧版浏览器支持:需要兼容 IE9 等不支持 History API 的浏览器
  3. 简单原型开发:快速搭建不需要复杂服务器配置的应用
  4. 混合应用:在传统多页应用中嵌入 SPA 模块

七、注意事项

  1. SEO 限制:搜索引擎对 hash 路由的索引支持有限
  2. URL 美观度URL 中的 # 符号可能影响美观
  3. 路由嵌套:与 BrowserRouter 的嵌套路由语法相同
  4. 锚点冲突hash 路由可能与传统页面锚点功能冲突
  5. 服务器通信hash 部分不会发送到服务器

总结

HashRouterReact Router 提供的一种简单易用的路由解决方案,特别适合不需要服务器配置需要兼容旧浏览器的场景。虽然它在 URL 美观度和 SEO 方面不如 BrowserRouter,但在特定环境下仍是不可或缺的工具。


网站公告

今日签到

点亮在社区的每一天
去签到