React中组件的生命周期(详细)
Posted MaNqo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React中组件的生命周期(详细)相关的知识,希望对你有一定的参考价值。
组件的生命周期
今天学习了组件的生命周期~
理解
- 生命周期的回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子
- 组件从创建到死亡经历的一些特定的阶段
- React组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用
- 我们在定义组件的时候,会在特定的生命周期回调函数中做特定的工作。
1 .组件的挂载和卸载
首先讲一下出生与死亡——挂载与卸载。
(1)当 Clock
组件第一次被渲染到 DOM 中的时候,就为其设置一个计时器。这在 React 中被称为“挂载(mount)
”。(2)同时,当 DOM 中 Clock
组件被删除的时候,应该清除计时器。这在 React 中被称为“卸载(unmount)
”。在组件挂载完毕的时候Life
的实例对象会调用componentDidMount()
这个函数,而在组件将要卸载的时候会调用componentWillunmount()
函数。
接下来通过这个demo展示一下挂载和卸载组件的应用:
这是一个通过类式组件实现的demo,一进入页面的时候上面的文字就会发生透明度会一直发生改变(挂载组件),当点击“你好”按钮的时候,上面的文字就会消失(卸载组件)
- 首先,注意定时器的位置:先创建一个组件,通过改变状态
state
的opacity
,在每一次改变state
的值的时候都会调用一次render
的函数。此时如果将定时器放在render
里面的话是会导致透明度的变化越来越快(定时器叠加),此时我们就需要使用挂载完毕之后调用的函数componentDidMount()
。 - 接下来给按钮添加功能,也就是让它在点击的时候调用
death
这个函数来卸载这个组件,在这之前,我们应该把定时器先清除了(组件不存在了,那么定时器也没有存在的必要了)。此时我们可以调用componentWillunmount
函数(这个函数会在组件将要卸载的时候调用),或者把清除定时器的语句放在ReactDOM.unmountComponentAtNode
之前也是可以的。
state = { opacity: 1 }
componentDidMount() {
this.timer = setInterval(() => {
let { opacity } = this.state;
opacity -= 0.1;
if (opacity <= 0) opacity = 1;
this.setState({ opacity });
}, 200);
}
componentWillunmount() {
clearInterval(this.timer);
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'));
}
ReactDOM.unmountComponentAtNode
用来卸载在某个结点上的组件。通过这个小demo可以很好的理解挂载和卸载的实际应用。生命周期函数的调用很写的时候它们的顺序无关。
接下来就进入生命周期的学习啦!
2. 生命周期(旧)
这张图的思路很清晰。需要注意的是,我们前面说过每一次setState
的时候会调用一次render
,其实不只是render
,shouldComponentUpdate
和componentWillUpdate
也会再次被调用。shouldComponentUpdate
决定了组件是否应该被更新,默认返回true,如果手动去把它的返回值更改为false,那么阀门被关闭,组件不会被更新。但如果调用的是强制更新函数forceUpdate()
,不会受到shouldComponentUpdate
返回值(阀门)的影响。
父组件render
下面这段代码的父组件就是A,子组件是B。通过在父组件的render
的返回值中添加<B str={this.state.str} />
来实现对B的渲染。子组件会受到父组件的影响(传值)。
class A extends React.Component {
state = { str: 'A' };
changeStr = () => {
this.setState({ str: 'B' })
}
render() {
return (
<div>
<div>A组件(父)</div>
<button onClick={this.changeStr}>change</button>
<B str={this.state.str} />
</div>
)
}
}
class B extends React.Component {
componentWillReceiveProps(props) {
console.log('B_componentWillReceiveProps', props);
}
render() {
return (
<div>B组件(子):{this.props.str} </div>
)
}
}
ReactDOM.render(<A />, document.getElementById('test'));
实现效果:
componentWillReceiveProps
在刚开始进入页面的时候是不调用的,点击按钮后(也就是父组件再次调用render
),<B str={this.state.str} />
这句语句重新执行,才会调用componentWillReceiveProps
。
总结生命周期(旧)
生命周期的三个阶段
(1) 初始化阶段: 由ReactDOM.render()
触发—初次渲染
-
constructor()
-
componentWillMount()
-
render()
-
componentDidMount()
—常用一般在这个钩子中初始化。例如:开启定时器、发送网络请求u、订阅消息等。
(2) 更新阶段: 由组件内部this.setSate()
或父组件重新render触发
shouldComponentUpdate()
(强制更新其实就是少了这个环节componentWillUpdate()
render()
—必用componentDidUpdate()
(3) 卸载组件: 由ReactDOM.unmountComponentAtNode()
触发 1. componentWillUnmount()
—常用一般1在这个钩子中做收尾工作。例如:关闭定时器、取消订阅消息等。
3. 生命周期(新)
新旧版本生命周期的区别
新版本与旧版本生命周期不同的是,(即将)启用了componentWillMount
、componentWillReceiveProps
、componentWillUpDate
这三个函数,如果要使用的话,需要在前缀添加UNSAFE
。并且,对于新版本的生命周期,多了两个函数,在挂载和更新时多了一个getDerivedStateFromProps
函数,在render
和componentDidUpdate
之间多了一个getSnapshotBeforeUpdate
函数。
在react官方文档中我们可以看到下面这段话。如果我们使用的是新版本的依赖包,在下面这几个函数没有添加UNSAFE
前缀的话,那么将会出现waring
警告。
接下来说新版本出现的2个新函数:
getDerivedStateFromProps()
(基本不用): 得到一个派生的状态。需要用static
来定义,需要返回一个状态对象state obj
或null
;能够接收到一个参数props
并且返回它。如果调用这个函数的话,state
的值在任何时候都取决于props
,无论初始化或者修改都无法改变。使用场景:state在任何时候都取决于props。
但是,派生状态会导致代码冗余,并使组件难以维护
static getDerivedStateFromProps(props, state) {
console.log(props, state); // 这个state使初始化状态的属性和属性值
return props;
}
ReactDOM.render(<Count count="100" />, document.getElementById('test'));
-
getSnapshotBeforeUpdate()
和componentDidUpdate
配合使用,在最近一次渲染输出之前调用,使得组件能在发生更改之前从DOM中捕获一些信息(例如:滚动位置)。此生命周期的任何返回值都将作为参数传递给componentDidUpdate()
// 在页面出现效果之前存个副本 getSnapshotBeforeUpdate() { console.log("getSnapshotBeforeUpdate"); return 'mannqo' } componentDidUpdate(preProps, preState, snapshowValue) { console.log('componentDidUpdate', preProps, preState, snapshowValue); }
应用场景:内容不断更新渲染,当你获得它在某一时刻的渲染结果。(比如不断渲染新的
li
,当溢出的时候显示滚动条,此时如果你滚动到某一个li
之后,由于不断渲染着新的li
,滚动条会自动发生滚动,此时如果你想让滚动条不滚动,那么就要用到getSnapshotBeforeUpdate()
总结
重要的钩子:
render
: 初始化渲染或更新渲染调用componentDidMount
: 开始监听,发送ajax
请求componentWillUnmount
: 做一些收尾工作,如:清除定时器
今天的学习就到这里啦!明天继续加油~
以上是关于React中组件的生命周期(详细)的主要内容,如果未能解决你的问题,请参考以下文章