Skip to content

Commit

Permalink
feat: support react-router v6
Browse files Browse the repository at this point in the history
  • Loading branch information
qiqiboy committed May 13, 2022
1 parent 0612c76 commit 2ff39cf
Show file tree
Hide file tree
Showing 13 changed files with 855 additions and 679 deletions.
68 changes: 37 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

react 路由切换动画,支持嵌套路由 (nested routers)和动态路由(dynamic routers)。

> 当前版本要求`react-router-dom``v6`版本,如果您还在使用`v4``v5`,请查看 [[email protected]](https://github.com/qiqiboy/react-animated-router/tree/0.2.4)
### 安装

```bash
Expand All @@ -21,8 +23,8 @@ import 'react-animated-router/animate.css'; //导入默认的切换动画样式
>
> 如果路由在多个页面文件中都有定义,为了避免每次都需要同时导入 react-animated-router 和 animate.css(如果只有一处引入 animate.css,其它地方不引入的话,在有 code split 的项目中,可能会有样式丢失),有两种办法可以优化:
>
> * 一,将`animate.css`在入口文件中引入,其它地方可以只引用 react-animated-router
> * 二,将 react-animated-router 和 animate.css 包装到一个模块文件中再默认导出,在其他地方引用该新模块:
> - 一,将`animate.css`在入口文件中引入,其它地方可以只引用 react-animated-router
> - 二,将 react-animated-router 和 animate.css 包装到一个模块文件中再默认导出,在其他地方引用该新模块:
```javascript
// 自己项目中的AnimatedRouter模块
Expand All @@ -35,49 +37,57 @@ export { default } from 'react-animated-router'; //直接将react-animated-route

### 如何使用

`AnimatedRouter`是一个标准的 React 组件,类似`react-router`中的`Switch`,将它放入你的项目中,然后在需要支持动画的地方,使用`AnimatedRouter`替换你的`Switch`组件即可。
`AnimatedRouter`是一个标准的 React 组件,它可以给一组`Route`组件增加动画切换效果,将它放入你的项目中,然后在需要支持动画的地方,使用`AnimatedRouter`替换你的`Routes`组件即可。

| 属性 | 类型 | 默认值 | 描述 |
| :-----------: | :----------: | :---------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| prefix | 字符串,可选 | `animated-router` | 应用到 CSSTransition 组件的 classNames 前缀。如果要在同一个项目中使用不同的动画,可以通过设置前缀来定义不同的动画。关于如何自定义动画,请查看下方说明 |
| timeout | 数字,可选 || 动画持续时间(毫秒),可以不传,默认为监听 transitionend 时间来判断动画结束。如果有动画异常,可以尝试设置该值,需要注意的是,该值应该与动画样式中定义的过渡时间一致 |
| className | 字符串,可选 || 如果传入 className 则会添加到动画节点所在容器节点上 |
| transitionKey | 字符串,可选 || 即每个页面节点需要的 key 值,如果不传则会使用当前页面地址的 pathname。<br/>该属性可以用于处理路由页面中还有子路由时的情况,用来避免子路由切换会导致父级页面也一块被重载。 |
| component | 布尔,可选 | 'div' | AnimatedRouter 默认会 render 一个 div 节点,你可以通过该字段修改 render 的节点类型,例如,`component="section"`将会 render `<section>`节点。在 react v16+中,可以传入 `null` 来避免渲染该节点。 |
| appear | 布尔,可选 | false | [文档:appear](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-appear):是否启用组件首次挂载动画(启用的话将会触发 enter 进场动画) |
| enter | 布尔,可选 | true | [文档:enter](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-enter):是否启用进场动画 |
| exit | 布尔,可选 | true | [文档:exit](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-exit):是否启用离场动画 |
**`AnimatedRouter` 对于嵌套的路由声明也有效!**

> 例如,可以对父级路由使用 AnimatedRouter 时定义使用父级路由 path 当作 key:
> transitionKey={this.props.location.pathname.split('/').slice(0, 2).join('/')}
| 属性 | 类型 | 默认值 | 描述 |
| :-----------: | :-------------------: | :---------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| location | `Location` 对象,可选 | 当前页面地址 | 等同于`Routes`的同名属性 |
| prefix | 字符串,可选 | `animated-router` | 应用到 CSSTransition 组件的 classNames 前缀。如果要在同一个项目中使用不同的动画,可以通过设置前缀来定义不同的动画。关于如何自定义动画,请查看下方说明 |
| timeout | 数字,可选 || 动画持续时间(毫秒),可以不传,默认为监听 transitionend 时间来判断动画结束。如果有动画异常,可以尝试设置该值,需要注意的是,该值应该与动画样式中定义的过渡时间一致 |
| className | 字符串,可选 || 如果传入 className 则会添加到动画节点所在容器节点上 |
| transitionKey | 字符串,可选 || 该属性用于标识路由动画节点,默认情况下为变换的路由所对应的`pathname`地址;`AnimatedRouter`已经智能处理了路由嵌套的情形,一般无需特定制定该参数。如果在嵌套路由场景中,要控制子路由变换时,父级路由的动画方式,可以传递该参数 |
| component | 布尔,可选 | 'div' | AnimatedRouter 默认会 render 一个 div 节点,你可以通过该字段修改 render 的节点类型,例如,`component="section"`将会 render `<section>`节点。在 react v16+中,可以传入 `null` 来避免渲染该节点。 |
| appear | 布尔,可选 | false | [文档:appear](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-appear):是否启用组件首次挂载动画(启用的话将会触发 enter 进场动画) |
| enter | 布尔,可选 | true | [文档:enter](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-enter):是否启用进场动画 |
| exit | 布尔,可选 | true | [文档:exit](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-exit):是否启用离场动画 |

```javascript
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Route, Redirect, Switch, BrowserRouter } from 'react-router-dom';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import AnimatedRouter from 'react-animated-router'; //导入我们的的AnimatedRouter组件
import 'react-animated-router/animate.css'; //导入默认的切换动画样式,如果需要其它切换样式,可以导入自己的动画样式定义文件

import Login from 'modules/Login';
import Signup from 'modules/Signup';
import NestLayout from 'modules/NestLayout';
import Nested from 'modules/Nested';

class App extends Component {
function App() {
render() {
/** 假如你的代码如此,则可直接使用最下方代码代替,即直接使用 AnimatedRouter 替换掉Switch
/** 假如你的代码如此,则可直接使用最下方代码代替,即直接使用 AnimatedRouter 替换掉 Routes
* return (
* <Switch>
* <Route path="/login"` component={Login} />
* <Route path="/signup" component={Signup} />
* <Redirect to="/login" />
* </Switch>
* <Routes>
* <Route path="login"` element={<Login />} />
* <Route path="signup" element={<Signup />} />
* <Route path="nested" element={<NestLayout />}>
* <Route path="1" element={<Nested id="1" />} />
* <Route path="2" element={<Nested id="2" />} />
* </Route>
* </Routes>
* );
**/

return (
<AnimatedRouter>
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Redirect to="/login" />
<Route path="login"` element={<Login />} />
<Route path="signup" element={<Signup />} />
<Route path="nested" element={<NestLayout />}>
<Route path="1" element={<Nested id="1" />} />
<Route path="2" element={<Nested id="2" />} />
</Route>
</AnimatedRouter>
);
}
Expand Down Expand Up @@ -113,9 +123,5 @@ render(

### FAQ

* **Q: 动画执行异常?**
- **Q: 动画执行异常?**
A: 可以尝试设置 timeout 属性,并保持与动画样式中定义的过渡时间一致(默认的 animate.scss 中为 300

---

更多说明以及我在探索路由动画应用中所遇到的坑,可以阅读我的[博客文章](http://www.qiqiboy.com/post/111)
15 changes: 15 additions & 0 deletions animate.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
width: 100%;
overflow: hidden;
}
.animated-router-forward-appear {
opacity: 0;
}
.animated-router-forward-appear-active {
opacity: 1;
}
.animated-router-forward-enter {
transform: translate(100%);
}
Expand All @@ -24,6 +30,12 @@
.animated-router-forward-exit-active {
transform: translate(-100%);
}
.animated-router-backward-appear {
opacity: 1;
}
.animated-router-backward-appear-active {
opacity: 0;
}
.animated-router-backward-enter {
transform: translate(-100%);
}
Expand All @@ -36,6 +48,9 @@
.animated-router-backward-exit-active {
transform: translate(100%);
}
.animated-router-forward-appear-active, .animated-router-backward-appear-active {
transition: opacity 0.3s linear;
}
.animated-router-forward-enter-active, .animated-router-forward-exit-active, .animated-router-backward-enter-active, .animated-router-backward-exit-active {
/* 不同过渡阶段需要的过渡时间与缓动效果 */
transition: transform 0.3s linear;
Expand Down
39 changes: 8 additions & 31 deletions dist/AnimatedRouter.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { Component, ReactType } from 'react';
import React, { ReactType } from 'react';
import { Location, RouteObject } from 'react-router';
import { TransitionActions } from 'react-transition-group/Transition';
import { RouteComponentProps } from 'react-router';
import PropTypes from 'prop-types';
import './animate.scss';
interface AnimatedRouterProps extends TransitionActions {
className?: string;
transitionKey?: string | number;
timeout?: number;
prefix?: string;
component?: ReactType | null;
location?: Location;
children: React.ReactNode | RouteObject[];
}
/**
* @desc 路由动画组件
Expand All @@ -18,31 +19,7 @@ interface AnimatedRouterProps extends TransitionActions {
* import AnimatedRouter from 'react-animated-router';
* import 'react-animated-router/animate.css';
*/
declare class AnimatedRouter extends Component<AnimatedRouterProps & RouteComponentProps> {
static propTypes: {
className: PropTypes.Requireable<string>;
transitionKey: PropTypes.Requireable<any>;
timeout: PropTypes.Requireable<number>;
prefix: PropTypes.Requireable<string>;
appear: PropTypes.Requireable<boolean>;
enter: PropTypes.Requireable<boolean>;
exit: PropTypes.Requireable<boolean>;
component: PropTypes.Requireable<any>;
};
static defaultProps: {
prefix: string;
};
inTransition: boolean;
rootNode: Element;
lastTransitionNode: Element;
setInTransition(isAdd: any): void;
onEnter: (node: any) => void;
onEntering: (node: any) => void;
onEntered: (node: any) => void;
componentDidMount(): void;
render(): JSX.Element;
}
declare const _default: React.ComponentClass<Pick<AnimatedRouterProps & RouteComponentProps<{}, import("react-router").StaticContext, any>, "enter" | "exit" | "timeout" | "className" | "transitionKey" | "prefix" | "component" | "appear"> & {
wrappedComponentRef?: ((instance: AnimatedRouter | null) => void) | React.RefObject<AnimatedRouter> | null | undefined;
}, any> & import("react-router").WithRouterStatics<typeof AnimatedRouter>;
export default _default;
declare const AnimatedRouter: React.FC<AnimatedRouterProps & {
_parentPath?: string;
}>;
export default AnimatedRouter;
Loading

0 comments on commit 2ff39cf

Please sign in to comment.