1 生命周期的理解
1.1 引出生命周期
需求:
- 让指定的文本做显示* / 隐藏的渐变动画
- 从完全可见,到彻底消失,耗时2S
- 点击“不活了”按钮从界面中卸载组件
源码及笔记如下:
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
46
47
48
49
50
51
52
|
class Life extends React.Component {
//只要页面发生更新,则说明是状态在驱动
state = {
opacity: 0.5
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
//和render一样 是由React帮忙调用的 因此不用写成箭头函数的形式
//执行时机:组件挂载到页面后
componentDidMount() {
//起个名字 挂到实例自身 方便清除时用
this.timer = setInterval(() => {
//获取状态值
let opacity = this.state.opacity
//每次-0.1
opacity -= 0.1
if (opacity <= 0) opacity = 1
//设置新的透明度
this.setState({ opacity })
}, 200)
}
//执行时机:组件将要被卸载
componentWillUnmount() {
clearInterval(this.timer)
}
//执行时机:初始化渲染、状态更新后
render() {
//如果将定时器函数放到render中,那么由于定时器中更新了state值,render函数就会不断被调用
//从而形成无限递归
// setInterval(() => {
// //获取状态值
// let opacity = this.state.opacity
// //每次-0.1
// opacity -= 0.1
// if (opacity <= 0) opacity = 1
// //设置新的透明度
// this.setState({ opacity })
// }, 200)
return (
<div>
<h2 style={{ opacity: this.state.opacity }}>React学不会怎么办</h2>
<button onClick={this.death}>不活了</button>
</div>
)
}
}
ReactDOM.render(<Life />, document.getElementById('test'))
|
1.2 生命周期的理解
合适的时间节点做合适的事
- 组件从创建到死亡它会经历一些特定的阶段。
- React 组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
- 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
2 React生命周期(旧)
2.1 React生命周期图(旧)
.png)
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
class Count extends React.Component {
//构造器
constructor(props) {
super(props)
console.log('Count---constructor');
//初始化状态
this.state = { count: 0 }
}
//组件将要挂载的钩子
componentWillMount() {
console.log('Count---componentWillMount');
}
//组件是否更新的钩子 相当于"阀门"
shouldComponentUpdate() {
console.log('Count---shouldComponentUpdate');
return true
}
//组件将要更新的钩子
componentWillUpdate() {
console.log('Count---componentWillUpdate');
}
// 加一事件的回调
add = () => {
const { count } = this.state
this.setState({ count: count + 1 })
}
//强制更新组件的回调
force = () => {
this.forceUpdate()
}
//组件更新完毕的钩子
componentDidUpdate() {
console.log('Count---componentDidUpdate');
}
render() {
console.log('Count---render');
const { count } = this.state
return (
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更新状态,只是强制更新一下组件</button>
</div>
)
}
//组件挂载完毕的钩子
componentDidMount() {
console.log('Count---componentDidMount');
}
//组件将要卸载的钩子
componentWillUnmount() {
console.log('Count---conponentWillUnmount');
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
}
//父组件A
class A extends React.Component {
//初始化状态
state = {
carName: '奔驰'
}
changeCar = () => {
this.setState({ carName: '奥迪' })
}
render() {
return (
<div>
<div>我是A组件</div>
<button onClick={this.changeCar}>点我切换汽车信息</button>
<B carName={this.state.carName} />
</div>
)
}
}
//子组件B
class B extends React.Component {
//第一次打开界面 发现其未运行 点击按钮后才会运行此钩子
//改名为componentWillReceiveNewProps更为准确
//组件将要接收新的props的钩子
componentWillReceiveProps() {
console.log('B---componentWillReceiveProps', this.props);
}
//控制组件更新的阀门
shouldComponentUpdate() {
console.log('B---shouldComponentUpdate');
//只要写了此钩子 必须return一个布尔值
return true
}
//组件将要更新的钩子
componentWillUpdate() {
console.log('B---componentWillUpdate');
}
//组件更新完毕的钩子
componentDidUpdate() {
console.log('B---componentDidUpdate');
}
render() {
console.log('B---render');
return (
<div>我是B组件,接受到的汽车是{this.props.carName}</div>
)
}
}
ReactDOM.render(<Count />, document.getElementById('test'))
|
2.2 总结生命周期(旧)
生命周期的三个阶段(旧):
- 初始化阶段: 由 ReactDOM.render()触发—初次渲染
1. constructor()
2. componentWillMount()
3. render()
4. **componentDidMount**()
一般在此钩子中做一些初始化的事:开启定时器,发送网络请求、订阅消息
-
更新阶段: 由组件内部 this.setSate()或父组件重新 render 触发
1. shouldComponentUpdate()
2. componentWillUpdate()
3. **render**()
4. componentDidUpdate()
-
卸载组件: 由 ReactDOM.unmountComponentAtNode()触发
1. componentWillUnmount()
一般做一些收尾的事:关闭定时器、取消订阅消息
2.3 React生命周期图(新)
.png)
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
class Count extends React.Component {
//构造器
constructor(props) {
super(props)
console.log('Count---constructor');
//初始化状态
this.state = { count: 0 }
}
//通过props获取派生状态对象
static getDerivedStateFromProps(props, state) {
console.log('Count---getDerivedStateFromProps', props, state);
return null//必须有返回值,返回值可以是null也可以是state对象
//return {count:2}//会覆盖初始化的state,且影响更新过程,setState方法失效(因为横跨挂载和更新过程)
//return props //可以接收props作为参数并返回 使得state值在任何时候都取决于props
}
//在更新之前获取快照
getSnapshotBeforeUpdate() {
console.log('Count---getSnapshotBeforeUpdate');
return 'atguigu'//返回null或者snapshot值(任何值)
}
//组件是否更新的钩子 相当于"阀门"
shouldComponentUpdate() {
console.log('Count---shouldComponentUpdate');
return true
}
// 加一事件的回调
add = () => {
const { count } = this.state
this.setState({ count: count + 1 })
}
//强制更新组件的回调
force = () => {
this.forceUpdate()
}
//组件更新完毕的钩子
//默认接收两个参数,分别是prevProps,prevState和snapshot值(例如滚轮位置)
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('Count---componentDidUpdate', prevProps, prevState, snapshot);
}
render() {
console.log('Count---render');
const { count } = this.state
return (
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更新状态,只是强制更新一下组件</button>
</div>
)
}
//组件挂载完毕的钩子
componentDidMount() {
console.log('Count---componentDidMount');
}
//组件将要卸载的钩子
componentWillUnmount() {
console.log('Count---conponentWillUnmount');
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
}
ReactDOM.render(<Count count={199} />, document.getElementById('test'))
|
2.4 总结生命周期(新)
生命周期的三个阶段(新)
1.初始化阶段: 由 ReactDOM.render()触发—初次渲染
1. constructor()
2. **getDerivedStateFromProps**()
3. render()
4. componentDidMount() 即将出生的那一刻
2.更新阶段: 由组件内部 this.setSate()或父组件重新 render 触发
1. getDerivedStateFromProps ()
2. shouldComponentUpdate()
3. **render**()
4. getSnapshotBeforeUpdate()
5. componentDidUpdate()
-
卸载组件: 由 ReactDOM.unmountComponentAtNode()触发
1. **componentWillUnmount**() 即将离去的那一刻
2.5 新旧生命周期对比
即将在18版本废除三个钩子(willmount,willupdate,willreceiveprops)
新增了两个钩子(getDerivedStateFromProps,getSnapshotBeforeUpdate)