Vue-Router 哈希路由 vs 历史路由详解

一、核心区别概览

特性 哈希模式 (hash mode) 历史模式 (history mode)
URL 格式 http://example.com/#/home http://example.com/home
原理 监听 hashchange 事件 使用 History API (pushState/replaceState)
兼容性 IE8+ IE10+
服务器配置 无需特殊配置 需要配置支持
SEO 不友好 友好(需要 SSR 配合)

二、哈希模式 (Hash Mode)

  1. 实现原理
javascript 复制代码
// Vue Router 内部实现简化版
class HashRouter {
  constructor() {
    // 1. 监听 hashchange 事件
    window.addEventListener('hashchange', () => {
      this.handleHashChange(window.location.hash);
    });
    
    // 2. 初始加载
    window.addEventListener('load', () => {
      if (!window.location.hash) {
        window.location.hash = '/';
      }
    });
  }
  
  handleHashChange(hash) {
    // 去除 # 号
    const path = hash.slice(1) || '/';
    // 路由匹配和渲染...
  }
  
  push(path) {
    window.location.hash = path;
  }
}
  1. 特点分析
javascript 复制代码
// URL 示例
// 完整URL: https://example.com/#/user/profile
console.log(window.location);
/*
{
  href: "https://example.com/#/user/profile",
  hash: "#/user/profile",     // 路由信息在这里
  pathname: "/",              // 始终是根路径
  search: "",                 // 查询参数在hash前
  hostname: "example.com"
}
*/

// 哈希变化不会触发页面刷新
// 只会触发 hashchange 事件
window.onhashchange = function(event) {
  console.log('旧URL:', event.oldURL);
  console.log('新URL:', event.newURL);
};
  1. 配置方式
javascript 复制代码
// Vue Router 配置
import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),  // 使用哈希历史
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

三、历史模式 (History Mode)

  1. 实现原理
javascript 复制代码
// Vue Router 内部实现简化版
class HistoryRouter {
  constructor() {
    // 1. 监听 popstate 事件(浏览器前进后退)
    window.addEventListener('popstate', (event) => {
      this.handlePopState(event.state);
    });
    
    // 2. 拦截链接点击(阻止默认行为)
    document.addEventListener('click', (e) => {
      if (e.target.tagName === 'A' && e.target.href) {
        e.preventDefault();
        this.push(e.target.getAttribute('href'));
      }
    });
  }
  
  push(path) {
    // 使用 History API 添加记录
    window.history.pushState({ path }, '', path);
    // 手动触发路由更新
    this.updateRoute(path);
  }
  
  replace(path) {
    window.history.replaceState({ path }, '', path);
    this.updateRoute(path);
  }
  
  handlePopState(state) {
    this.updateRoute(state?.path || window.location.pathname);
  }
}
  1. History API 详解
javascript 复制代码
// 核心 API 方法

// 1. pushState - 添加历史记录(不会触发页面刷新)
history.pushState(state, title, url);
// 示例:
history.pushState({ page: 1 }, "Page 1", "/page1");

// 2. replaceState - 替换当前历史记录
history.replaceState(state, title, url);
// 示例:
history.replaceState({ page: 2 }, "Page 2", "/page2");

// 3. popstate 事件 - 监听前进后退
window.addEventListener('popstate', (event) => {
  console.log('位置变化到:', event.state);
});

// 4. 获取当前状态
const currentState = history.state;
  1. 配置方式
javascript 复制代码
// Vue Router 配置
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),  // 使用 HTML5 历史模式
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/:pathMatch(.*)*', component: NotFound } // 404页面
  ]
})

四、服务器配置差异

  1. 哈希模式(无需配置)
bash 复制代码
# 所有请求都返回 index.html
# 哈希部分由前端处理
https://example.com/#/about  → 返回 index.html
https://example.com/#/user/1 → 返回 index.html
  1. 历史模式(必须配置)

nginx文件

bash 复制代码
# Nginx 配置示例
server {
    listen 80;
    server_name example.com;
    root /usr/share/nginx/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;  # 关键:重定向到 index.html
    }
}

apache文件

bash 复制代码
# Apache .htaccess 配置
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

javascript文件

javascript 复制代码
// Node.js Express 配置
const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'dist')));

// 所有路由都返回 index.html
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});

五、优缺点对比

哈希模式

优点:

兼容性好(支持 IE8+)

无需服务器特殊配置

部署简单,适合静态托管

不会发起服务器请求(hash变化)

缺点:

URL 不美观,有 # 符号

SEO 不友好,爬虫可能忽略 hash 部分

某些锚点功能冲突

历史模式

优点:

URL 美观,无 # 符号

SEO 友好(配合 SSR 更佳)

完整的 URL 路径语义

可以利用完整的 URL 进行分享

缺点:

需要服务器支持(所有路由返回 index.html)

兼容性要求 IE10+

部署配置相对复杂

相关推荐
小迷糊的学习记录5 小时前
0.1 + 0.2 不等于 0.3
前端·javascript·面试
空&白5 小时前
vue暗黑模式
javascript·vue.js
VT.馒头6 小时前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
css趣多多6 小时前
一个UI内置组件el-scrollbar
前端·javascript·vue.js
-凌凌漆-6 小时前
【vue】pinia中的值使用 v-model绑定出现[object Object]
javascript·vue.js·ecmascript
大橙子额9 小时前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
vortex59 小时前
几种 dump hash 方式对比分析
算法·哈希算法
WooaiJava10 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
LYFlied10 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
Never_Satisfied10 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html