react-smooth-router
v1.2.0
Published
一个带有平滑过渡动画的 React 路由库,和react-router-config兼容,支持页面切换动画
Maintainers
Readme
React Smooth Router
一个带有平滑过渡动画的 React 路由库,支持页面进入和退出动画,以及参数化路由。
安装
npm install react-smooth-router
# 或者
yarn add react-smooth-router特性
- 流畅的页面过渡动画
- 支持页面前进和后退的不同动画效果
- 支持参数化路由(如
/product/:id) - 保持页面滚动位置
- 适配移动设备和桌面设备
- 支持嵌套路由
- 支持通配符路由
- 支持精确匹配和前缀匹配
- 支持自定义动画时间
基本用法
配置式路由(推荐)
使用renderRoutes函数可以更方便地配置和管理路由:
// routes.ts
import { RouteConfig } from 'react-smooth-router';
import Home from './pages/Home';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';
import NotFound from './pages/NotFound';
const routes: RouteConfig[] = [
{
path: '/',
component: Home,
exact: true
},
{
path: '/page1',
component: Page1
},
{
path: '/page2',
component: Page2
},
{
path: '*',
component: NotFound
}
];
export default routes;// App.tsx
import React, { useEffect } from 'react';
import { createBrowserHistory } from 'history';
import { Router, renderRoutes, PageContainer } from 'react-smooth-router';
import 'react-smooth-router/dist/styles.css'; // 引入样式
import routes from './routes';
// 创建浏览器历史对象
const history = createBrowserHistory();
const App: React.FC = () => {
useEffect(() => {
// 监听路由变化
const unlisten = history.listen(({ location, action }) => {
console.log('Navigation:', action, location.pathname);
});
return () => unlisten();
}, []);
// 将routes配置转换为React元素
const routeElements = renderRoutes(routes);
return (
<div className="app-container" style={{ height: '100vh', width: '100%' }}>
<Router history={history}>
<PageContainer maxPages={4}>
{routeElements}
</PageContainer>
</Router>
</div>
);
};
export default App;页面组件示例
// Home.tsx
import React from 'react';
import { Link } from 'react-smooth-router';
const Home: React.FC = () => {
return (
<div className="page home-page">
<h1>首页</h1>
<div className="buttons">
<Link to="/page1" className="btn">前往页面1</Link>
<Link to="/page2" className="btn">前往页面2</Link>
<Link to="/page3" className="btn">前往页面3</Link>
<Link to="/page4" className="btn">前往页面4</Link>
<Link to="/page5" className="btn">前往页面5</Link>
<Link to="/page6" className="btn">前往页面6</Link>
<Link to="/non-existent" className="btn">不存在的页面</Link>
</div>
</div>
);
};
export default Home;
// Page1.tsx
import React from 'react';
import { Link, useRouter } from 'react-smooth-router';
const Page1: React.FC = () => {
const { navigationDirection } = useRouter();
return (
<div className="page page1">
<h1>页面1</h1>
<p>当前导航方向: {navigationDirection}</p>
<div className="buttons">
<Link to="/" className="btn">返回首页</Link>
<Link to="/page2" className="btn">前往页面2</Link>
<Link back={true} className="btn">返回上一页</Link>
</div>
</div>
);
};
export default Page1;使用示例:类似原生App的页面保留机制与滑动动画
React Smooth Router 能够实现类似原生App的页面过渡效果:
- 进入新页面时,页面从右侧滑入
- 返回上一页时,页面从左侧滑入
- 保留页面状态和滚动位置
- 缓存最近访问的页面,提高性能
这在构建移动端Web应用时尤其有用,可以提供更接近原生App的用户体验。
// 带滑动菜单的移动应用示例
import React, { useState } from 'react';
import { Router, PageContainer, renderRoutes } from 'react-smooth-router';
import { createBrowserHistory } from 'history';
import routes from './routes';
const history = createBrowserHistory();
const MobileApp: React.FC = () => {
const [menuOpen, setMenuOpen] = useState(false);
const routeElements = renderRoutes(routes);
return (
<div className={`mobile-app ${menuOpen ? 'menu-open' : ''}`}>
<div className="menu-toggle" onClick={() => setMenuOpen(!menuOpen)}>
☰
</div>
<div className="side-menu">
<div className="menu-header">应用菜单</div>
<div className="menu-items">
<div onClick={() => { history.push('/'); setMenuOpen(false); }}>首页</div>
<div onClick={() => { history.push('/page1'); setMenuOpen(false); }}>页面1</div>
<div onClick={() => { history.push('/page2'); setMenuOpen(false); }}>页面2</div>
</div>
</div>
<div className="content-container">
<Router history={history}>
<PageContainer maxPages={5}>
{routeElements}
</PageContainer>
</Router>
</div>
</div>
);
};
export default MobileApp;API 参考
RouteConfig
路由配置对象,用于renderRoutes函数。
interface RouteConfig {
path: string; // 路由路径
component: React.ComponentType; // 要渲染的组件
exact?: boolean; // 是否精确匹配路径
routes?: RouteConfig[]; // 子路由配置
[key: string]: any; // 其他自定义属性
}renderRoutes
将路由配置转换为React元素。
function renderRoutes(
routes: RouteConfig[] = [],
extraProps: Record<string, unknown> = {},
parentPath?: string
): React.ReactElement | null参数:
routes: 路由配置数组extraProps: 传递给组件的额外属性parentPath: 父路由路径,用于嵌套路由
Router
路由容器组件,用于管理路由状态和历史记录。
<Router history={history}>
{/* 应用内容 */}
</Router>Props:
history: 历史记录对象,如createBrowserHistory()创建的对象
PageContainer
页面容器组件,用于管理页面之间的过渡动画。
<PageContainer maxPages={5}>
{/* J_Page 组件 */}
</PageContainer>Props:
maxPages: 最多缓存的页面数量,默认为5
J_Page
页面组件,用于定义路由和页面内容。
<J_Page path="/about" exact={false}>
<About />
</J_Page>Props:
path: 路由路径exact: 是否精确匹配,默认为falseisActive: 手动控制页面激活状态isTransitioning: 手动控制过渡状态
Link
导航链接组件。
<Link to="/about">关于我们</Link>
<Link back={true}>返回</Link>Props:
to: 目标路径back: 是否返回上一页replace: 是否替换当前历史记录state: 传递的状态数据
useRouter
路由钩子,用于获取路由信息和导航方法。
const { location, navigationDirection, navigate, goBack } = useRouter();返回值:
location: 当前路由信息navigationDirection: 导航方向('forward' | 'backward')navigate: 导航方法goBack: 返回方法
样式
默认提供了以下CSS类:
j-page: 页面基础类active: 激活状态root-page-hide: 隐藏状态page-enter-forward: 前进进入动画page-enter-active-forward: 前进进入动画激活page-exit-forward: 前进退出动画page-exit-active-forward: 前进退出动画激活page-enter-backward: 后退进入动画page-enter-active-backward: 后退进入动画激活page-exit-backward: 后退退出动画page-exit-active-backward: 后退退出动画激活
自定义动画
可以通过覆盖默认样式来自定义动画效果:
.j-page {
transition: transform 0.3s ease-in-out;
}
.page-enter-forward {
transform: translateX(100%);
}
.page-enter-active-forward {
transform: translateX(0);
}
.page-exit-forward {
transform: translateX(0);
}
.page-exit-active-forward {
transform: translateX(-100%);
}
.page-enter-backward {
transform: translateX(-100%);
}
.page-enter-active-backward {
transform: translateX(0);
}
.page-exit-backward {
transform: translateX(0);
}
.page-exit-active-backward {
transform: translateX(100%);
}嵌套路由
支持嵌套路由配置:
const routes = [
{
path: '/dashboard',
component: Dashboard,
routes: [
{
path: '/dashboard/overview',
component: Overview
},
{
path: '/dashboard/users',
component: Users
}
]
}
];嵌套路由组件接收子路由:
function Dashboard({ children }) {
return (
<div>
<h1>仪表盘</h1>
<nav>
<Link to="/dashboard/overview">概述</Link>
<Link to="/dashboard/users">用户</Link>
</nav>
<div className="dashboard-content">
{/* 子路由内容将渲染在这里 */}
{children}
</div>
</div>
);
}更新日志
v1.1.0
- 优化了路径匹配逻辑
- 修复了首页路由匹配问题
- 改进了动画处理机制
- 优化了性能
- 完善了类型定义
- 更新了文档
v1.0.0
- 初始版本发布
许可
MIT
