文章目录
前言
什么是前端路由?前端路由有什么作用呢?前端路由又是如何实现的?常见的路由模式History
和 Hash
又有什么区别呢?VueRouter又是如何实现的?我们的日常项目又该怎么使用呢?我们再来一次,这一次我们好好来~
一、什么是前端路由?
前端路由是指在单页面应用(SPA,Single Page Application)
中,通过前端实现页面跳转和页面内容更新的一种机制。与服务器端路由不同,前端路由不需要重新加载整个页面,而是通过动态加载页面内容来实现页面的切换,从而提高用户体验和应用的响应速度。
前端路由,简单来说,就是在不刷新整个页面的情况下,改变网页的 URL 并展示不同的内容。
通常来讲,我们打开浏览器浏览一个网站的时候,点击不同的链接、按钮,页面会跳转到不同的内容,但是页面却没有进行完整的刷新,这就是前端路由在起作用。
二、前端路由的作用
- 无刷新页面跳转: 用户在应用中切换页面时,不需要重新加载整个页面,而是通过动态加载页面内容实现。
- URL管理: 每个页面的URL都与实际内容相对应,便于用户访问和分享。
- 组件化: 每个路由对应一个组件,当路由被激活时,对应的组件会被加载和渲染。
- 性能提升: 避免了页面的重新加载,前端路由可以减少服务器请求和网络传输,从而提高应用的性能和响应速度。
- 安全性: 通过路由守卫(如权限验证),前端路由可以进行访问校验,防止未授权访问。
- 历史管理: 前端路由可以管理浏览器的历史记录,支持前进和后退操作,使得用户在浏览过程中可以像访问传统多页面应用一样使用浏览器的前进和后退功能。
- SEO友好: 通过
服务器端渲染(SSR)
或预渲染(Prerendering)
技术在服务端生成静态的HTML页面
,从而提高搜索引擎的访问度。但是URL 的哈希部分不会被搜索引擎索引。
三、前端路由是如何实现的?
1. 关键步骤
- 监听URL 变化: 当用户点击链接或进行其他操作时,前端路由会监听 URL 的变化。
- 根据路由规则匹配页面: 前端路由会根据当前的 URL 匹配预先定义好的路由规则,例如:
/about 对应关于我们页面
/products 对应产品列表页面 - 渲染对应内容: 根据匹配到的路由规则,前端路由会动态地渲染对应的内容,并将渲染结果展示在页面上。
2. 结合Vue框架中的Vue Router内部实现
2.1 使用 history 模式
Vue Router history
模式的内部实现主要依赖于浏览器的 history
API,尤其是 history.pushState
和 history.replaceState
方法。
History 模式下,浏览器会将所有 URL 都发送给服务器
- 配置路由规则匹配页面
const router = new VueRouter({
mode: 'history', // 启用 history 模式
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact },
{ path: '/*', component: NotFound } // 404 路由
]
});
- 修改URL
(1) 点击浏览器的前进或后退按钮
popstate
事件只会在浏览器某些行为下触发,点击浏览器的前进或后退按钮时(或者在 JavaScript 中调用 history.back() 方法)
// 监听 popstate 事件
window.addEventListener('popstate', (event) => {
router.push(location.pathname);
});
(2) 使用 pushState 和 replaceState 改变 URL
用户点击一个路由链接或通过编程式导航(如 this.$router.push
)跳转时,Vue Router 会使用 history.pushState
或 history.replaceState
来改变 URL:
// 编程式导航
this.$router.push('/about');
// 相当于
history.pushState({}, '', '/about'); // pushState(state, unused, url); state传递的参数对象,unused: 空值,url: 相对路由
(3) 直接在地址栏修改URL
这就涉及到另一个问题,也就是在浏览器输入URL会发生什么,这个我们后面再讲!
- 根据路由规则匹配页面
当URL
变化时,路由库会根据定义的路由规则
找到匹配的页面或组件,一旦匹配成功,Vue Router
会将对应的组件渲染到<router-view>
组件的位置。这通常涉及到以下步骤:- 匹配 URL: 路由库会检查当前 URL 与定义的路由规则,找到匹配的路由。
- 加载组件: 一旦找到匹配的路由,路由库会加载对应的组件,并将其插入到
DOM
中。
- 路由守卫
路由守卫机制,允许你在路由跳转前后执行一些操作。路由守卫可以访问路由对象,执行权限验证、数据获取等操作:
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/about',
component: About,
beforeEnter: (to, from, next) => {
// 执行权限验证
if (userCanAccess) {
next();
} else {
next('/unauthorized');
}
}
}
]
});
2.2 使用 hash模式
利用 URL 的哈希部分(即 # 后面的部分)来进行路由的识别和跳转。这种模式不需要服务器配置,适合简单的单页面应用(SPA)。
URL 哈希部分: URL 的哈希部分(# 后面)通常被浏览器忽略,不会触发页面的重新加载。因此,可以通过改变哈希部分来实现页面内容的动态加载。
监听哈希变化: Vue Router 监听 URL 哈希的变化,当哈希变化时,触发路由的匹配和组件的渲染。
window.addEventListener('hashchange', () => {
router.push(window.location.hash);
});
- 路由匹配: 根据哈希部分的内容,Vue Router 匹配对应的路由规则,并渲染相应的组件。
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'hash', // 使用 hash 模式
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact }
]
});
四、History
和 Hash
的区别
特性 | history 模式 | hash 模式 |
---|---|---|
URL 形式 | 正常 URL(http://www.example.com/about) | 带有 # 号的 URL(http://www.example.com/#/about) |
数据传输 | History 模式使用 HTTP 协议 进行数据传输 |
# 符号后面的部分 |
工作原理 | 依赖于浏览器 HTML5 History API |
利用 URL 中 # 号后的部分来标识不同的页面 |
服务器配置 | 必须需要服务器配置 URL 重写规则(History 模式依赖于服务器的 URL 重写功能,将所有请求都指向 index.html 文件) |
所有的路由处理都在前端完成 |
SEO | 友好 | 不利于 SEO(URL 的哈希部分不会被搜索引擎索引) |
用户体验 | 更接近传统网页浏览 | 可能存在一些兼容性问题 |
五、日常项目使用建议
优先选择 History 模式: 如果你的项目对 SEO 有要求,并且服务器端可以配置 catch-all
路由,建议优先选择 History 模式。
考虑 Hash 模式: 如果你的项目对 SEO 要求不高,或者无法进行服务器端配置,可以使用 Hash 模式。
注意刷新页面问题: 无论选择哪种模式,都要注意处理刷新页面导致的页面跳转问题。可以使用 history.pushState
或者 history.replaceState
方法来控制浏览器历史记录,避免页面跳转。
六、Vue项目打包后直接打开HTML显示白屏,路由router-view不加载问题
1. 原因分析
当直接加载 index.html
时,浏览器会请求 file:///path/to/index.html
,导致 History 模式失效。这是因为:
本地文件系统: 当你直接双击 index.html
文件或使用 file:///
协议打开它时,浏览器会将它视为一个本地文件,而不是一个服务器上的资源。
服务器配置: History 模式
依赖于服务器的 URL 重写
功能,将所有请求都指向 index.html
文件。但在本地文件系统中,浏览器无法访问服务器,因此 URL 重写功能也无法生效。
2. 具体来说:
History 模式下的 URL: 在 History 模式
下,URL 通常看起来像正常的网页链接,例如 http://localhost:8080/about
。但实际上这只是单页应用的内部路由,服务器并不会真正找到一个名为 about 的文件。
服务器的 URL 重写: 为了解决这个问题,你需要在你的服务器上配置 URL 重写
规则,将所有请求都指向 index.html
文件。这样,当用户访问 http://localhost:8080/about
时,服务器会将请求转发到 index.html
,然后由 Vue Router
处理路由逻辑,最终渲染出对应的页面。
本地文件系统:
当你直接在本地文件系统中打开 index.html
时,浏览器无法访问服务器,也就无法进行 URL 重写,因此 History 模式
失效。
3. 解决方案
使用 Vue Router
的 Hash
模式时,URL 会包含一个 #
符号,例如 http://localhost:8080/#/about
。这种模式下,浏览器会将 #
符号后面的内容作为内部 URL,并不会向服务器发送请求。因此,Vue Router
可以直接解析 # 符号后面的 URL,而不需要服务器进行 URL 重写。
// src/router/index.js
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
}
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router;
总结一下
前端路由
在单页应用程序(SPA
)中扮演着关键角色,通过在不重新加载整个页面的情况下更新 URL 并渲染不同的视图
,实现平滑的页面导航和状态管理。这种技术不仅提升了用户体验,使应用响应更加迅速,还简化了前端开发流程。前端路由在很多前端框架(如 Vue
、React
、Angular
)中广泛应用,允许开发者构建功能丰富、动态更新的 Web 应用,实现类似多页应用的导航效果,同时保留单页应用的高效性。前端路由通常使用两种模式:history 模式
和 hash 模式
。history 模式
使用浏览器的 History API
来管理路由,而 hash 模式
则通过 URL
的哈希部分(#
)来实现路由。这两种模式各有优缺点,根据具体需求选择合适的模式尤为重要。