前言

eg:代表代码对照 若文章有误,欢迎读者留言反馈

React核心包如何降级

安装17.0.2的React核心包
npm i -S react@17.0.2 react-dom@17.0.2 核心包降级

入口文件重新引入ReactDOM、配置

17.0.2入口文件

1
2
3
4
5
6
7
8
9
import React from 'react'
import ReactDOM from 'react' // 17.0.2引入写法
import App from './App'

// 17.0.2 入口写法 注意语法
ReactDOM.render(
<App />,
document.getElementById('root')
)

18.2入口文件

1
2
3
4
5
6
7
8
9
10
import React from 'react'
import ReactDOM from 'react-dom/client' // 18.2引入写法
import App from './App'

// 18.2 入口写法 注意语法
// root 类似于vue中 Vue构造函数的实例 18.2语法
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<App />
)

过渡动画组件

安装react-transition-group,它是react的第三方模块

npm i -S react-transition-group

自定义动画

  1. 安装完引入CSSTransition标签,并对齐进行配置
    import { CSSTransition } from 'react-transition-group'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 1. 安装完引入CSSTransition标签
import { CSSTransition } from 'react-transition-group'

class Transition extends Component {
state = {
show: false
}
handleClick = () => {
this.setState({
show: !this.state.show
})
}
render() {
return (
<div>
<h3>过渡动画</h3>
{/* 2. 使用CSSTransition,并对其配置 */}
<CSSTransition
in={this.state.show} // 动画开关
timeout={2000} // 动画时长
classNames='donghua' // class
unmountOnExit // 可选,加上代表离场动画执行完毕删除当前节点
>
<div>动画元素</div>
</CSSTransition>
<button onClick={this.handleClick}>开关</button>
</div>
)
}
}
  1. 书写样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.donghua-enter {
/* 开始执行动画 隐藏*/
opacity: 0;
}
.donghua-enter-active {
/* 入场动画 */
opacity: 1;
transition: opacity 2000ms;
}
.donghua-exit {
/* 离场 */
opacity: 1;
}
.donghua-exit-active {
/* 离场中 */
opacity: 0;
transition: opacity 2000ms;
}
  1. 引入动画样式到组件中

import './trans.css'

使用动画库

animate.css动画库集成到react-transition-group动画模块中

Animate.css官网

安装插件【已经安装的不需要重复安装】
npm i -S react-transition-group
npm i -S animate.css

入口文件引入动画库
// 使用动画库
import 'animate.css'

组件中使用
引入CSSTransition标签:import { CSSTransition } from 'react-transition-group'

1
2
3
4
5
6
7
8
9
10
11
12
13
<CSSTransition
in={this.state.show} // 开关
timeout={2000} // 动画时长
classNames={{
enter: 'animate__animated',
enterActive: 'animate__fadeIn',
exit: 'animate__animated',
exitActive: 'animate__fadeOut'
}} //class组
unmountOnExit // 离场动画执行完毕要不要删除当前节点
>
<div>这个是动画元素</div>
</CSSTransition>

列表过渡动画

多个CSSTransition标签这时候需要TransitionGroup动画组包裹住

引入CSSTransition和TransitionGroup标签

import { CSSTransition, TransitionGroup } from 'react-transition-group'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React, { Component } from 'react'
import { CSSTransition, TransitionGroup } from 'react-transition-group'
// 列表动画
export default class Transition3 extends Component {
state = {
list: [1, 2, 3, 4],
show: false
}
handleClick = () => {
this.setState({
show: !this.state.show
}, () => {
console.log(this.state.show)
})
}
render() {
return (
<div>
<button onClick={this.handleClick}>动画</button>
{/* 使用TransitionGroup标签 */}
<TransitionGroup>
{
this.state.list.map((item, index) => {
return (
<CSSTransition
in={this.state.show}
timeout={1000}
// classNames="myfade"
unmountOnExit
onEntered={(el) => { el.style.color = 'blue' }} //钩子函数等价于enter
appear={true} //启动首屏 首屏就执行动画
key={index}
>
<div>
{item}
</div>
</CSSTransition>
)
})
}
</TransitionGroup>
</div>
)
}
}

路由过渡动画【使用V5版本React-Router,,,5.3.0】

安装路由模块

路由模块不是react自带模块,需要安装第三方模块
npm i -S react-router-dom

入口文件引入hash路由模式,HashRouter标签

import { HashRouter } from 'react-router-dom'

使用HashRouter标签

1
2
3
<HashRouter>
<App />
</HashRouter>,

回到根组件配置二级路由,引入路由需要的标签和组件,由于使用17.0.2版本引入一下高阶组件withRouter,使用location

import { Switch,Route,Link,withRouter } from 'react-router-dom'
import Home from './pages/Home'
import User from './pages/user'

1
2
3
4
5
6
7
8
9
10
11
return (
<>
{/* react的空标签是<></> vue的空标签是template标签 */}
<Link to="/home">home</Link>
<Link to="/user">user</Link>
<Switch>
<Route path="/home" component={Home} />
<Route path="/user" component={User} />
</Switch>
</>
)

引入动画相关标签
import { CSSTransition, TransitionGroup } from 'react-transition-group'

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import React, { Component } from 'react'
import { Switch, Route, Link, withRouter } from 'react-router-dom'
import Home from './pages/Home'
import User from './pages/User'
import { CSSTransition, TransitionGroup } from 'react-transition-group'

class App extends Component {
render() {
// render初始执行一次,location值为undefined,不能.pathname会报错,这里使用短路运算符解决
console.log(this.props.location && this.props.location.pathname) //当前的路由pathname
return (
<>
{/* react的空标签是<></> vue的空标签是template标签 */}
<Link to="/home">home</Link> |
<Link to="/user">user</Link>
<TransitionGroup>
<CSSTransition
// in={true} //路由切换会自动触发组件的创建和销毁
timeout={2000}
// classNames="myfade"
classNames={{
enter: 'animate__animated',
enterActive: 'animate__slideInLeft',
exit: 'animate__animated',
exitActive: 'animate__slideOutLeft'
}}
unmountOnExit //离场之后 页面组件销毁
key={this.props.location && this.props.location.pathname}
>
<Switch>
<Route path="/home" component={Home} />
<Route path="/user" component={User} />
</Switch>
</CSSTransition>
</TransitionGroup>
</>
)
}
}
// react-router-dom 17.0.2版本,只要拿不到路由相关的属性和对象就使用高阶withRouter
export default withRouter(App)

利用高阶组件给组件添加动画

并不想让所有的路由都有动画效果,只是想对指定的页面有路由切换效果,可以利用高阶组件来完成。

定义高阶组件【函数组件】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React from 'react'
// 引入CSSTransition标签
import { CSSTransition } from 'react-transition-group'
// 动画过渡的高阶组件
export default function TransHoc(Component) {
// 可以返回函数组件也可以返回类组件【函数组件没有this,需要传入props,然后直接使用】
return function newCom(props) {
console.log('匹配:', props.match)
// this.props.match 是匹配时候的路由对象,如果没有匹配就null
// 例如:/user User null
return <CSSTransition
in={props.match !== null} // 不为null代表匹配上了,开启动画
timeout={2000}
classNames={{
enter: 'animate__animated',
enterActive: 'animate__fadeIn',
exit: 'animate__animated',
exitActive: 'animate__fadeOut'
}}
unmountOnExit
>
<Component {...props} />
</CSSTransition>
}
}

使用高阶组件,如果有配置装饰器支持,可以使用高阶组件语法糖@高阶组件名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from 'react'
// 引入高阶组件
import HOCTransition from '../HOC/HOCTransition'

class Home extends Component {
render() {
return (
<div style={{background: 'red'}}>
Home
</div>
)
}
}
// 使用高阶组件
export default HOCTransition(Home)

配置路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import React, { Component } from 'react'
import { Route } from 'react-router-dom'
import Home from './pages1/Home'
import User from './pages1/User'
/*
高阶组件,给我们的页面组件添加动画效果,把效果添加在Home页面组件
*/
export default class App1 extends Component {
render() {
return (
<div>
{/* <Route path="/home" component={ Home }></Route>
<Route path="/User" component={ User }></Route> */}
{/* component 注册的组件,会触发创建和销毁, children*/}
{/* children初始化的时候,页面就会被创建,只有在匹配路由的时候才渲染 */}
{/* children属性使用,17.0.2支持,18.2暂时没有替代方法 */}
<Route path="/home" children={props => <Home {...props} />}></Route>
<Route path="/User" children={props => <User {...props} />}></Route>
</div>
)
}
}

注意:暂时没发现`children`如何使用`v6版本`替代,暂留、降级`v5版本`