关于前端路由
1. 什么是前端路由?
前端路由是一种客户端路由技术,它通过改变 URL 来动态渲染不同的组件或页面,而不需要向服务器发送请求。主要功能包括:
- 根据 URL 显示不同的组件。
- 支持页面之间的跳转。
- 支持 URL 参数和查询字符串。
- 提供路由守卫(如登录验证)。
2. React Router
React Router 是 React 官方推荐的路由库,支持 React 网页应用的动态路由管理。
2.1 安装
npm install react-router-dom
2.2 基础用法
示例代码:
import React from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
function Home() {
return <h1>Home Page</h1>;
}
function About() {
return <h1>About Page</h1>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
解释:
BrowserRouter
:用于包裹整个应用,启用路由功能。Routes
和Route
:定义路由规则,Route
的path
指定 URL,element
指定要渲染的组件。Link
:用于导航,代替传统的<a>
标签。
2.3 动态路由与参数
function User({ id }) {
return <h1>User ID: {id}</h1>;
}
function App() {
return (
<Router>
<Routes>
<Route path="/user/:id" element={<User />} />
</Routes>
</Router>
);
}
解释:
:id
是动态参数,可以通过useParams
获取:
import { useParams } from "react-router-dom";
function User() {
const { id } = useParams();
return <h1>User ID: {id}</h1>;
}
2.4 路由守卫(认证)
通过高阶组件或条件渲染实现路由守卫。
示例代码:
function PrivateRoute({ children }) {
const isAuthenticated = true; // 假设已登录
return isAuthenticated ? children : <Navigate to="/login" />;
}
function App() {
return (
<Router>
<Routes>
<Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
<Route path="/login" element={<Login />} />
</Routes>
</Router>
);
}
解释:
PrivateRoute
是一个路由守卫组件,只有用户登录后才会渲染<Dashboard />
。
2.5 扩展
- 嵌套路由:允许在路由中嵌套子路由。
- 懒加载:使用
React.lazy
和Suspense
实现组件的按需加载。
const About = React.lazy(() => import('./About'));
3. Vue Router
3.1 安装
npm install vue-router@4
3.2 基础用法
示例代码:
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{ path: "/", component: () => import("./views/Home.vue") },
{ path: "/about", component: () => import("./views/About.vue") },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
在 main.js
中引入:
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
createApp(App).use(router).mount("#app");
在组件中使用 <router-link>
和 <router-view>
:
<template>
<nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</nav>
<router-view></router-view>
</template>
解释:
createRouter
:创建路由实例。routes
:定义路由规则。router-link
:用于导航,代替传统的<a>
标签。router-view
:渲染匹配的组件。
3.3 动态路由与参数
示例代码:
const routes = [
{ path: "/user/:id", component: () => import("./views/User.vue") },
];
在组件中通过 useRoute
获取参数:
import { useRoute } from "vue-router";
export default {
setup() {
const route = useRoute();
const id = route.params.id;
return { id };
},
};
3.4 路由守卫(认证)
通过 beforeEach
实现路由守卫。
示例代码:
router.beforeEach((to, from, next) => {
const isAuthenticated = true; // 假设已登录
if (to.path === "/dashboard" && !isAuthenticated) {
next("/login");
} else {
next();
}
});
解释:
beforeEach
是全局路由守卫,用于验证用户权限。
3.5 扩展
- 嵌套路由:在
routes
中使用children
定义子路由。 - 懒加载:使用动态导入实现组件的按需加载。
component: () => import("./views/About.vue");
4. 子路由
4.1 定义子路由
在 Vue 中,子路由通过children属性实现。
// router.js
import { createRouter, createWebHistory } from "vue-router";
import Home from "./views/Home.vue";
import User from "./views/User.vue";
import UserProfile from "./views/UserProfile.vue";
import UserPosts from "./views/UserPosts.vue";
const routes = [
{ path: "/", component: Home },
{
path: "/user/:id",
component: User,
children: [
// 子路由
{ path: "profile", component: UserProfile },
{ path: "posts", component: UserPosts },
],
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
User.js
父组件示例:
<template>
<div>
<h1>User - ID: {{ id }}</h1>
<nav>
<router-link :to="`/user/${id}/profile`">Profile</router-link>
<router-link :to="`/user/${id}/posts`">Posts</router-link>
</nav>
<!-- 子组件渲染的位置 -->
<router-view></router-view>
</div>
</template>
<script>
import { useRoute } from "vue-router";
export default {
setup() {
const route = useRoute();
const id = route.params.id;
return { id };
},
};
</script>
UserProfile.vue
子组件示例:
<template>
<div>User Profile</div>
</template>
UserPosts.vue
子组件示例:
<template>
<div>User Posts</div>
</template>
运行效果
- 访问
/user/1
,显示父组件User
。 - 访问
/user/1/profile
,显示父组件User
和子组件UserProfile
。 - 访问
/user/1/posts
,显示父组件User
和子组件UserPosts
。
在 React 中,子路由通过嵌套 <Route>
组件实现。
代码示例:
// App.js
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import User from "./User";
import UserProfile from "./UserProfile";
import UserPosts from "./UserPosts";
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/user/1">User 1</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:id" element={<User />}>
{/* 子路由 */}
<Route path="profile" element={<UserProfile />} />
<Route path="posts" element={<UserPosts />} />
</Route>
</Routes>
</Router>
);
}
export default App;
User.js
父组件示例:
import { Outlet, Link, useParams } from "react-router-dom";
function User() {
const { id } = useParams();
return (
<div>
<h1>User - ID: {id}</h1>
<nav>
<Link to="profile">Profile</Link>
<Link to="posts">Posts</Link>
</nav>
{/* 子组件渲染的位置 */}
<Outlet />
</div>
);
}
export default User;
UserProfile.js
子组件示例:
function UserProfile() {
return <div>User Profile</div>;
}
export default UserProfile;
UserPosts.js
子组件示例:
function UserPosts() {
return <div>User Posts</div>;
}
export default UserPosts;
运行效果
- 访问
/user/1
,显示父组件User
。 - 访问
/user/1/profile
,显示父组件User
和子组件UserProfile
。 - 访问
/user/1/posts
,显示父组件User
和子组件UserPosts
。
4.2 子路由的作用:
作用:
-
页面分层: 将页面分为父组件和子组件,父组件负责公共布局(如导航栏、侧边栏),子组件负责具体的功能模块。
-
动态渲染: 根据 URL 的变化,动态渲染子组件的内容,而不需要重新加载整个页面。
-
代码解耦: 父组件和子组件的逻辑可以分离,便于维护和扩展。
-
URL 结构化: 通过嵌套路由,可以形成结构化的 URL,便于理解和 SEO 优化。
-
共享状态: 父组件和子组件可以共享状态或逻辑,减少重复代码。
子路由优点:
-
代码复用: 父组件的布局和逻辑可以复用在多个子组件中。
-
URL 清晰: 嵌套路由的 URL 结构清晰,易于理解和维护。
-
性能优化: 子路由只会重新渲染子组件,而不是整个页面。
-
功能隔离: 父组件和子组件的功能可以分离,便于单独开发和测试。
-
动态加载: 可以根据需要动态加载子组件,减少初始加载时间。
子路由的缺点:
-
复杂度增加: 子路由会增加应用的复杂度,尤其是多层嵌套时。
-
调试难度: 多层嵌套的路由结构可能会增加调试的难度。
-
路由冲突: 如果不小心设计,可能会导致路由冲突或无法匹配。
4.3 子路由的应用场景:
1. 后台管理系统
- 场景: 后台管理系统通常有一个公共布局(如顶栏、侧边栏),而内容区域需要根据导航动态变化。
- 实现:
- 父组件:布局框架(顶栏、侧边栏)。
- 子组件:具体功能模块(如用户管理、订单管理、日志管理等)。
- 示例 URL:
/dashboard/users # 显示用户管理模块 /dashboard/orders # 显示订单管理模块
2. 用户中心
- 场景: 用户中心页面包含多个子页面(如个人资料、订单列表、设置等),这些子页面共享用户中心的基本布局。
- 实现:
- 父组件:用户中心的布局(如用户信息展示)。
- 子组件:具体功能模块(如个人资料、订单列表、设置等)。
- 示例 URL:
/user/profile # 显示个人资料 /user/orders # 显示订单列表
3. 多级导航
- 场景: 复杂的应用可能有多级导航结构,子路由可以轻松实现这种嵌套关系。
- 实现:
- 父组件:一级导航页面。
- 子组件:二级导航页面。
/category/electronics # 显示电子产品类别 /category/electronics/phones # 显示手机子类别
4. 标签页(Tab)
- 场景: 标签页的内容需要通过 URL 切换,子路由可以方便地实现这种功能。
- 实现:
- 父组件:标签页的容器。
- 子组件:每个标签页的内容。
- 示例 URL:
/settings/profile # 显示个人资料标签页 /settings/security # 显示安全设置标签页
5. 嵌套模态框
- 场景: 点击某个页面元素(如按钮)后,弹出一个模态框,模态框的内容需要根据 URL 动态加载。
- 实现:
- 父组件:基础页面。
- 子组件:模态框内容。
- 示例 URL:
/products # 显示产品列表 /products/123 # 显示产品 123 的模态框
5. 总结
React Router
- 使用
BrowserRouter
、Routes
和Route
定义路由。 - 支持动态路由、路由守卫和懒加载。
- 适合 React 应用。
Vue Router
- 使用
createRouter
和routes
定义路由。 - 支持动态路由、路由守卫和懒加载。
- 适合 Vue 应用。
拓展思路
- 路由懒加载:提升应用性能。
- 嵌套路由:构建复杂的页面结构。
- 路由守卫:实现权限控制。
- 自定义路由插件:扩展路由功能,如基于角色的权限管理。