1. Vue Router:如何优雅地配置 404 页面
在单页面应用 (SPA) 的开发过程中,路由跳转是核心功能。然而,当用户访问一个不存在的 URL 时,如果没有妥善处理,页面可能会空白或直接报错。本文将详细介绍如何在 Vue Router 中配置 404 页面。
1.1 为什么要配置 404 页面
配置 404 页面不仅是为了美观,更是为了:
- 提升用户体验:避免用户看到崩溃的白屏。
- 保护应用安全性:隐藏内部路由结构,防止恶意探测。
- 引导用户:提供返回首页或搜索的建议。
1.2 核心配置方法
Vue Router 提供了通配符路由 来实现这一功能。通过将路径设置为 *,我们可以捕获所有未匹配到的路由。
1.2.1 路由匹配逻辑流程
下图展示了 Vue Router 匹配路由的过程:
#publish-mermaid-1785469800554-0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785469800554-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785469800554-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785469800554-0 .error-icon{fill:#552222;}#publish-mermaid-1785469800554-0 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785469800554-0 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785469800554-0 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785469800554-0 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785469800554-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785469800554-0 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785469800554-0 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785469800554-0 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785469800554-0 .marker.cross{stroke:#333333;}#publish-mermaid-1785469800554-0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785469800554-0 p{margin:0;}#publish-mermaid-1785469800554-0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785469800554-0 .cluster-label text{fill:#333;}#publish-mermaid-1785469800554-0 .cluster-label span{color:#333;}#publish-mermaid-1785469800554-0 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785469800554-0 .label text,#publish-mermaid-1785469800554-0 span{fill:#333;color:#333;}#publish-mermaid-1785469800554-0 .node rect,#publish-mermaid-1785469800554-0 .node circle,#publish-mermaid-1785469800554-0 .node ellipse,#publish-mermaid-1785469800554-0 .node polygon,#publish-mermaid-1785469800554-0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785469800554-0 .rough-node .label text,#publish-mermaid-1785469800554-0 .node .label text,#publish-mermaid-1785469800554-0 .image-shape .label,#publish-mermaid-1785469800554-0 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785469800554-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785469800554-0 .rough-node .label,#publish-mermaid-1785469800554-0 .node .label,#publish-mermaid-1785469800554-0 .image-shape .label,#publish-mermaid-1785469800554-0 .icon-shape .label{text-align:center;}#publish-mermaid-1785469800554-0 .node.clickable{cursor:pointer;}#publish-mermaid-1785469800554-0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785469800554-0 .arrowheadPath{fill:#333333;}#publish-mermaid-1785469800554-0 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785469800554-0 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785469800554-0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785469800554-0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785469800554-0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785469800554-0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785469800554-0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785469800554-0 .cluster text{fill:#333;}#publish-mermaid-1785469800554-0 .cluster span{color:#333;}#publish-mermaid-1785469800554-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785469800554-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785469800554-0 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785469800554-0 .icon-shape,#publish-mermaid-1785469800554-0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785469800554-0 .icon-shape p,#publish-mermaid-1785469800554-0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785469800554-0 .icon-shape .label rect,#publish-mermaid-1785469800554-0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785469800554-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785469800554-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785469800554-0 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node rect,#publish-mermaid-1785469800554-0 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785469800554-0 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785469800554-0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}是否
用户发起请求 URL
Vue Router 进入路由守卫检查
匹配到有效路径?
渲染匹配到的组件
渲染通配符组件 (404 Page)
页面更新
1.2.2 代码实现
首先,你需要创建一个用于显示 404 错误信息的组件。
步骤 1:创建 NotFound 组件
在 src/views 目录下创建 NotFound.vue:
<template>
<div class="not-found-container">
<h1>404</h1>
<p>抱歉,您访问的页面不存在。</p>
<router-link to="/">返回首页</router-link>
</div>
</template>
<script>
export default {
name: "NotFound"
}
</script>
<style scoped>
.not-found-container {
text-align: center;
margin-top: 100px;
}
</style>
步骤 2:配置路由
在 src/router/index.js 中添加通配符路由。注意:通配符路由必须放在路由配置的最后,否则它会拦截所有路由请求。
import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/Home.vue";
import NotFound from "../views/NotFound.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/user/:id",
name: "User",
component: () => import("../views/User.vue")
},
// 关键配置:404 页面
{
path: "*",
component: NotFound
}
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
1.3 部署环境的注意事项
配置好前端路由后,在本地开发环境通常能正常显示 404 页面。但在生产环境部署(如使用 Nginx)时,可能会有特殊的处理需求。
1.3.1 单页应用 (SPA) 的路径问题
如果在生产环境中,直接访问不存在的路径(例如 /abc)出现 404 Not Found 错误,这可能是因为 Web 服务器(如 Nginx)找不到对应的 HTML 文件。为了避免这种情况,通常需要在 Nginx 配置中使用 try_files 指令,将所有请求转发给 index.html。
server {
listen 80;
server_name your-domain.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
如果上述配置生效,那么当访问不存在的路径时,Nginx 会将请求重写回 index.html,进而由 Vue Router 接管,成功展示我们配置的 404 组件。
1.4 总结
配置 Vue Router 的 404 页面非常简单,只需在路由配置文件中添加一个 path: '*' 的对象即可。但为了确保在服务器部署后的正常显示,还需注意服务端的静态资源转发配置。希望本文能帮助您完善项目的鲁棒性。





