Vue进阶:vue 路由的两种模式:hash与history_vue创建中的history

Vue进阶:vue 路由的两种模式:hash与history_vue创建中的history

一、背景与问题

在单页应用(SPA)开发中,页面跳转是核心功能之一。Vue Router 作为官方路由管理器,提供了两种模式:hash 模式和 history 模式。这两种模式在底层实现和应用场景上有显著差异,理解其原理和适用场景是构建健壮应用的关键。

核心问题

  1. 为什么需要两种模式?
  2. 它们在底层是如何工作的?
  3. 什么场景下应该选择哪种模式?
  4. 实际开发中可能遇到哪些陷阱?

二、基本原理

1. hash 模式原理

hash 模式通过 URL 的 # 后缀来实现路由。浏览器会忽略 # 后的内容,因此不会触发页面刷新。通过监听 hashchange 事件,可以捕获 URL 变化并更新页面内容。

关键点

  • URL 始终带有 # 前缀
  • 浏览器不会向服务器发送请求
  • 不需要服务器配置

2. history 模式原理

history 模式利用 HTML5 的 pushStatereplaceState API,直接修改浏览器历史记录。URL 中不包含 #,但会触发完整的页面加载过程。需要服务器配置来支持 404 页面重定向。

关键点

  • URL 与实际路径一致
  • 浏览器会向服务器发送请求
  • 需要服务器配置支持

三、环境准备

1. 项目初始化

npm init -y
npm install vue vue-router@4

2. 基础配置

// main.js
import { createApp } from 'vue'
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import App from './App.vue'

// 路由配置
const routes = [
  { path: '/', component: () => import('./views/Home.vue') },
  { path: '/about', component: () => import('./views/About.vue') }
]

// 创建路由实例
const router = createRouter({
  history: createWebHistory(), // 或 createWebHashHistory()
  routes
})

createApp(App).use(router).mount('#app')

四、核心实现

1. hash 模式实现

// router.js
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'

const routes = [
  { path: '/#/', component: Home },
  { path: '/#/about', component: About }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

关键代码解释

  • createWebHashHistory() 创建 hash 模式实例
  • 路由路径以 /#/ 开头
  • 浏览器自动处理 hashchange 事件

2. history 模式实现

// router.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

关键代码解释

  • createWebHistory() 创建 history 模式实例
  • 路由路径直接使用路径名
  • 需要服务器配置支持

3. 动态路由示例

// router.js
import { createRouter, createWebHistory } from 'vue-router'
import User from './views/User.vue'

const routes = [
  { 
    path: '/user/:id', 
    component: User,
    props: true // 将参数作为 props 传递
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

关键代码解释

  • 使用 :id 定义动态路由参数
  • props: true 将参数作为 props 传递给组件
  • 在组件中通过 this.$route.params.id 获取参数

五、完整案例

1. 博客系统案例

项目结构

blog-app/
├── index.html
├── main.js
├── router.js
├── views/
│   ├── Home.vue
│   ├── PostList.vue
│   └── PostDetail.vue
└── App.vue

配置文件

// router.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
import PostList from './views/PostList.vue'
import PostDetail from './views/PostDetail.vue'

const routes = [
  { path: '/', component: Home },
  { 
    path: '/posts', 
    component: PostList,
    children: [
      { 
        path: 'post/:id', 
        component: PostDetail,
        props: true
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

组件代码

<!-- Home.vue -->
<template>
  <div>
    <h1>博客首页</h1>
    <router-link to="/posts">查看所有文章</router-link>
  </div>
</template>
<!-- PostList.vue -->
<template>
  <div>
    <h2>文章列表</h2>
    <ul>
      <li v-for="post in posts" :key="post.id">
        <router-link :to="`/posts/post/${post.id}`">{{ post.title }}</router-link>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      posts: [
        { id: 1, title: 'Vue Router 入门' },
        { id: 2, title: '深入理解 Vue 3' }
      ]
    }
  }
}
</script>
<!-- PostDetail.vue -->
<template>
  <div>
    <h2>{{ post.title }}</h2>
    <p>{{ post.content }}</p>
  </div>
</template>

<script>
export default {
  props: ['id'],
  data() {
    return {
      post: {
        id: this.id,
        title: '默认文章',
        content: '这是默认内容'
      }
    }
  },
  mounted() {
    // 模拟从服务器获取数据
    this.post = {
      id: this.id,
      title: `文章 ${this.id}`,
      content: `这是文章 ${this.id} 的内容`
    }
  }
}
</script>

六、源码解析

1. history 模式核心逻辑

// vue-router/dist/vue-router.mjs
function createWebHistory(base = '/') {
  const history = {
    base,
    push: (path, state) => {
      // 调用浏览器 API 修改历史记录
      window.history.pushState(state, '', base + path)
    },
    replace: (path, state) => {
      window.history.replaceState(state, '', base + path)
    }
  }
  return history
}

关键点

  • 使用 pushStatereplaceState 修改历史记录
  • 需要服务器支持 404 重定向
  • URL 完全匹配路由路径

2. hash 模式核心逻辑

// vue-router/dist/vue-router.mjs
function createWebHashHistory(base = '/') {
  const history = {
    base,
    push: (path, state) => {
      // 调用浏览器 API 修改 hash
      window.location.hash = base + path
    },
    replace: (path, state) => {
      window.location.replace(base + path)
    }
  }
  return history
}

关键点

  • 直接操作 URL 的 hash 部分
  • 不需要服务器配置
  • URL 保持 # 前缀

七、进阶使用

1. 动态加载组件

const routes = [
  {
    path: '/dynamic',
    component: () => import('./views/Dynamic.vue')
  }
]

2. 嵌套路由

const routes = [
  {
    path: '/user',
    component: UserLayout,
    children: [
      { path: '', redirect: 'profile' },
      { path: 'profile', component: UserProfile },
      { path: 'posts', component: UserPosts }
    ]
  }
]

3. 路由守卫

const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      if (isAuthenticated()) {
        next()
      } else {
        next('/login')
      }
    }
  }
]

八、性能与工程实践

1. 性能优化

history 模式优化方案

  • 使用 vue-routerscrollBehavior 控制滚动位置
  • 启用 prefetch 预加载
  • 使用 vitewebpack 的代码分割
const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    return { top: 0 }
  }
})

2. 安全风险

常见风险

  • 路由参数注入
  • 前端验证不足
  • 跨站请求伪造(CSRF)

防护措施

  • 对所有参数进行校验
  • 启用 CORS 策略
  • 对敏感操作进行二次验证

3. 服务器配置

history 模式服务器配置示例(Nginx)

location / {
    try_files $uri $uri/ /index.html;
}

常见错误:未配置服务器导致 404 错误

九、常见问题与踩坑

1. 常见错误

错误 1:404 页面未处理

错误代码

// 未处理 404 页面

解决方法

const routes = [
  { path: '/:pathMatch(.*)', redirect: '/' }
]

错误 2:history 模式下页面刷新后空白

错误原因:服务器未正确配置

解决方法:确保服务器将所有请求重定向到 index.html

2. 常见陷阱

陷阱 1:URL 中的 # 未处理

错误代码

// 错误处理

解决方法:使用 window.location.hash 处理 hash 部分

陷阱 2:SEO 不友好

解决方案:使用 history 模式并配合服务器配置

十、最佳实践

1. 推荐方案

场景推荐模式原因
SEO 要求高historyURL 更友好
兼容性要求高hash无需服务器配置
单页应用history更符合 RESTful 风格

2. 实践建议

  • 始终使用 vue-routerbeforeEach 守卫
  • 对所有路由参数进行校验
  • 使用 vitewebpack 的代码分割优化性能
  • 遇到 404 错误时立即处理

十一、总结

Vue 路由的 hash 和 history 模式是构建单页应用的核心技术。理解它们的原理和差异,能够帮助开发者在不同场景下做出最佳选择。hash 模式适合对兼容性要求高的场景,而 history 模式更适合需要 SEO 支持的项目。实际开发中需要注意服务器配置、性能优化和安全防护,避免常见的坑。通过合理使用路由守卫、动态加载和嵌套路由,可以构建出更加健壮和高效的单页应用。

VUE
最后修改于:2026年09月15日 18:34

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日