当前位置: 首页 > news >正文

Vue的路由模式的区别和原理

路由模式

Vue 的路由模式指的是 Vue Router 提供的 URL 处理方式,主要有两种:Hash 模式和History 模式。

Hash模式

在 Vue Router 中,默认使用的是 hash 模式,即 mode: 'hash'。如果想要使用 history 模式,可以设置 mode: 'history'

原理

  • Hash 模式基于浏览器的 window.location.hash 属性。当 URL 中的哈希部分发生变化时,Vue Router 会监听到这个变化,并相应地切换视图。

  • Hash 模式不会向服务器发送请求。这是因为 URL 中的哈希值(# 后面的部分)的变化不会触发浏览器重新加载页面或向服务器发送新请求

核心原理

  1. 哈希值变化:当 URL 的哈希部分(如 http://example.com/#/home 中的 /home)发生变化时,浏览器只会:

    • 更新 window.location.hash 属性。
    • 触发 hashchange 事件(可通过 window.addEventListener(hashchange, callback) 监听)。
  2. Vue Router 的处理:Vue Router 监听 hashchange 事件,根据新的哈希值匹配对应的路由配置,然后动态更新组件视图。整个过程完全在前端完成,不会向服务器发送任何请求

  3. 下面是Vue3底层hash改变的代码实现(有兴趣可以看一下)

// 简化版 Vue Router 核心实现
class Router {constructor(options) {this.routes = options.routes || [];this.currentPath = window.location.hash.slice(1) || '/';// 创建响应式数据:使用 Vue 3 的 reactive 原理(简化版)this.currentRoute = this.createReactive({path: this.currentPath,component: null});// 初始化路由监听this.init();}// 创建简易响应式对象(模拟 Vue 3 的 Proxy 实现)createReactive(target) {return new Proxy(target, {set: (obj, key, value) => {obj[key] = value;this.updateView(); // 值变化时更新视图return true;}});}// 初始化路由监听init() {// 1. 初始加载时处理当前哈希值this.handleHashChange();// 2. 监听哈希值变化window.addEventListener('hashchange', () => {this.handleHashChange();});}// 处理哈希值变化handleHashChange() {this.currentPath = window.location.hash.slice(1) || '/';this.matchRoute();}// 匹配路由matchRoute() {const route = this.routes.find(route => {// 简化的路径匹配(实际 Vue Router 使用更复杂的路径解析)return route.path === this.currentPath;});if (route) {this.currentRoute.path = route.path;this.currentRoute.component = route.component;} else {// 处理 404 路由this.currentRoute.path = '*';this.currentRoute.component = this.routes.find(r => r.path === '*')?.component;}}// 更新视图(模拟 Vue 的虚拟 DOM 更新)updateView() {// 在实际 Vue Router 中,这里会触发 Vue 组件的重新渲染console.log(`路由变更为: ${this.currentRoute.path}`);}
}// 模拟 Vue 组件系统
function createComponent(options) {return {...options,render() {// 实际 Vue 会根据模板生成 VNode 并渲染console.log(`渲染组件: ${this.name}`);}};
}// 使用示例
const HomeComponent = createComponent({name: 'Home',template: '<div>Home Page</div>'
});const AboutComponent = createComponent({name: 'About',template: '<div>About Page</div>'
});const router = new Router({routes: [{ path: '/', component: HomeComponent },{ path: '/about', component: AboutComponent },{ path: '*', component: createComponent({ name: 'NotFound', template: '<div>404 Not Found</div>' }) }]
});// 模拟路由切换
window.setTimeout(() => {window.location.hash = '/about';
}, 2000);

Vue2设置Hash模式

import Vue from 'vue';
import VueRouter from 'vue-router';Vue.use(VueRouter);const routes = [// 路由配置
];const router = new VueRouter({mode: 'hash', // 使用 hash 模式routes
});new Vue({router,render: h => h(App)
}).$mount('#app');

Vue3设置Hash模式

import { createRouter, createWebHashHistory } from 'vue-router';// 导入组件
import Home from '../views/Home.vue';
import About from '../views/About.vue';// 定义路由
const routes = [{path: '/',name: 'Home',component: Home},{path: '/about',name: 'About',component: About}
];// 创建路由实例并配置 hash 模式
const router = createRouter({history: createWebHashHistory(), // 指定为 hash 模式routes
});export default router;

优势

  • 兼容性: Hash 模式在不同浏览器之间的兼容性较好,因为浏览器对于哈希部分的处理方式基本一致。
  • 无需服务器支持: 不需要后端服务器的特殊配置,可以在任意静态服务器上使用。

缺点

  • URL 美观度: URL 中带有 # 符号,可能不够美观。
  • SEO 不友好: 对搜索引擎的优化相对较差,因为搜索引擎不会将哈希部分的内容作为独立的页面来处理。

History模式

原理

在 Vue Router 中,History 模式基于 HTML5 的 History API 实现,通过操作浏览器的历史记录栈,在不刷新页面的情况下改变 URL ,同时还能实现前进、后退等导航功能
https://www.doubao.com/thread/wa13961c844859854

  1. NodeJs的配置实现
const http = require('http')
const fs = require('fs')
const httpPort = 80http.createServer((req, res) => {fs.readFile('index.html', 'utf-8', (err, content) => {if (err) {console.log('We cannot open "index.html" file.')}res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'})res.end(content)})
}).listen(httpPort, () => {console.log('Server listening on: http://localhost:%s', httpPort)
})

特点

  1. History 模式下的路由切换操作(如 pushState)本身确实不需要向后端发送请求
  2. 当用户直接访问 / 刷新子路由(如 http://example.com/about)时,浏览器会主动向后端发送请求,这才是需要后端配置的原因。

正常路由切换(通过 pushState

用户在页面内点击按钮触发 router.push('/about') 时:

  • 前端调用 history.pushState(),URL 变为 http://example.com/about(不刷新页面)。
  • 前端路由匹配 /about,渲染 About 组件(纯前端操作,无需后端参与)。

直接访问 / 刷新子路由(如输入 http://example.com/about 回车)

当用户直接在地址栏输入 http://example.com/about 并回车,或在该页面按 F5 刷新时:

  • 浏览器会认为这是一个全新的 HTTP 请求,按照 URL 的路径(/about)向服务器发送请求。

  • 服务器默认会找 /about 对应的物理文件,但前端路由是单页应用(只有 index.html),所以服务器找不到资源,返回 404。

  • 后端配置(如 Nginx 的 try_files、Express 的 * 路由)的核心逻辑是:
    无论请求的路径是什么(如 /about、/user),都返回前端的 index.html。

    • 这样,当用户直接访问 / 刷新子路由时:

    • 服务器返回 index.html → 浏览器加载 HTML 和 JS。

    • 前端路由启动,读取当前 URL(/about),匹配并渲染组件。

为什么 Hash 模式不需要处理这种情况

  • Hash 模式的 URL 是 http://example.com/#/about,浏览器在发送请求时,只会把 # 前面的部分(http://example.com/)发给服务器,所以服务器始终返回 index.html,前端路由能正常运行。

  • 而 History 模式的 URL 是 http://example.com/about(无 #),浏览器会把完整路径 /about 发给服务器,导致需要后端干预。

Vue3配置History模式

import { createRouter, createWebHistory } from 'vue-router'// 创建路由
const router = createRouter({history: createWebHistory(),// routes: routes 的缩写routes, 
})

优势

  • URL 美观度: URL 更加美观,不带有 # 符号。
  • SEO 友好: 对搜索引擎的优化更好,因为搜索引擎能够更好地处理没有哈希部分的 URL。

缺点

  • 兼容性: 兼容性相对较差,需要服务器的支持,且在某些环境中可能需要额外的配置。
  • 需要服务器支持: 刷新页面或直接访问某个路由时,服务器需要正确处理这个路由。

总结

  1. History 模式的路由切换本身(pushState)不需要后端参与,但“直接访问 / 刷新子路由”` 的场景会触发浏览器向后端发送请求,因此需要后端配置兜底规则(返回 index.html)。

  2. 服务器返回 index.html 后,前端路由会接管 URL 解析和组件渲染:

    • index.html 加载前端框架和路由逻辑。
    • 前端路由根据当前 URL(/about)匹配组件。
    • 动态渲染对应组件,最终显示你想要的页面。
  3. 这就是单页应用的核心:一个入口文件 + 前端路由动态渲染,实现 “看似多页,实则单页” 的体验。

http://www.dtcms.com/a/287436.html

相关文章:

  • RTSP推流客户端-ffmpeg和live555对比
  • Oracle Database 23ai 技术细节与医疗 AI 应用
  • windows docker-01-desktop install windows10 + wls2 启用
  • 加法速算之尾数法
  • 语音识别技术:从声音到文字的 AI 魔法
  • 多云联邦集群管理(1)(集群联邦管理)
  • 基于大模型打造故障预警服务器巡检机器人
  • World of Warcraft [CLASSIC] The Ruby Sanctum [RS] Halion
  • 【C# in .NET】19. 探秘抽象类:具体实现与抽象契约的桥梁
  • 用逻辑回归(Logistic Regression)处理鸢尾花(iris)数据集
  • 【专业扫盲】源极退化电阻
  • min_25筛学习笔记+牛客多校02E
  • NumPy 30分钟速成计划
  • 【运维心得】老旧系统迁移到虚拟机的另类解决
  • 力扣刷题(第九十二天)
  • nodejs值process.kill
  • 【RK3576】【Android14】固件烧录
  • 13.多种I/O函数
  • WPF为启动界面(Splash Screen)添加背景音乐
  • simulink系列之汽车应用层信号处理
  • android studio libs.versions.toml 配置
  • 计算机网络——IPv4(25王道最新版)
  • 从丢包到恢复:TCP重传机制的底层逻辑全解
  • Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战
  • nginx.conf模版
  • 使用DataGrip连接安装在Linux上的Redis
  • Datawhale AI数据分析 作业
  • TinyMCE 富文本编辑器在 vue2 中的使用 @tinymce/tinymce-vue
  • Django母婴商城项目实践(八)- 数据渲染与显示之首页
  • windows wsl2-05-docker 安装笔记