一、旧版本生命周期
1.constructor(构造器):主要用于初始化数据,这个组件可以省略,如下图所示。
//标准写法
class Demo extends React.component {
constructor(props){
super(props)
//只要用到构造器就需要super一下
this.state = {name:'张三'}
}
}
//简写
class Demo extends React.component {
state = {name:'张三'}
}
2.componentWillMount(组件将要挂载时):
3.render():这个是必须用的生命周期。
4.componentDidMount(组件挂载完毕时):进行一些创建完成后的操作,例如:创建定时器、请求网络、订阅消息等。这个生命周期是常用的。
5.shouldComponentUpdate(更新数据后要不要更新):当你修改state中的属性值后,就会调用这个方法。如果使用该生命周期一定要给返回值。返回值为false,那么页面上将不会进行更新操作。
6.componentWillUpadate(组件将要更新)
7.componentDidUpdate(组件更新完成后)
8.componentWillReceiveProps(父组件给子组件传参):这个生命周期在页面初始化的时候不调用,在点击页面更新的时候会调用。
class Father extends React.Component{
state = {weather:"晴天"}
QueryWeather=()=>{
this.setState({weather:'阴天'})
}
render(){
return (<div>
<h1>爸爸说:今天天气怎么样?</h1>
<button onClick={this.QueryWeather}>回答</button>
<Son weather={this.state.weather} />
</div>)
}
}
class Son extends React.Component{
componentWillReceiveProps(props){
console.log(props)
}
render(){
return (<div>
<h1>今天天气{this.props.weather}</h1>
</div>)
}
}
ReactDOM.render(<Father />,document.getElementById('text'))
9.componentWillUnmount(组件将要卸载):这个组件也是常用的。进行页面收尾工作,例如:清除定时器、取消订阅等。
生命周期执行流程图:(forceUpdate是强制更新,不修改状态中的值,直接更新)
然后我在说一下完整的流程:
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
- constructor()
- componentWillMount()
- render()
- componentDidMount()
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()
二、新版本生命周期
新版本与旧版本的区别在于新版本将会慢慢淘汰三个生命周期分别是componentWillMount()、
componentWillUpdate()和componentWillReceiveProps(),如果在新版本中需要使用的话,那就在前面添加UNSAFE_前缀,例如UNSAFE_componentWillReceiveProps(){};添加两个生命周期分别是getDerivedStateFromProps和getSnapshotBeforeUpdate。
不管是淘汰的这三个还是新加的这两个,在开发过程中都很少用到的,像getDerivedStateFromProps如果使用不当,则会造成数据冗余;只有参数一直都在state中才能使用它,但是能在这个生命周期里操作同样的也能在别的生命周期里操作,所以尽量不用。创建时需要加上static关键字使用。
getSnapshotBeforeUpdate:它可以把数据作为映射,白话说就是保存你修改值之前的值。下面是一个实例代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>4_getSnapshotBeforeUpdate的使用场景</title>
<style>
.list{
width: 200px;
height: 150px;
overflow: auto;
background-color: #1277dc;
}
.news{
height: 30px;
}
</style>
</head>
<body>
<div id="text"></div>
<script src="../../js/react.development.js"></script>
<script src="../../js/react-dom.development.js"></script>
<script src="../../js/babel.min.js"></script>
<script type="text/babel">
class Father extends React.Component{
state = {newsArr:[]}
componentDidMount(){
setInterval(() => {
// 获取原状态
const {newsArr} = this.state
// 模拟一条新闻
const news = '新闻'+(newsArr.length+1)
// 更新状态
this.setState({newsArr:[news,...newsArr]})
}, 1000);
}
getSnapshotBeforeUpdate(){
return this.refs.list.scrollHeight
}
componentDidUpdate(preProps,preState,height){
this.refs.list.scrollTop += this.refs.list.scrollHeight - height
}
render(){
return (
<div className="list" ref="list">
{
this.state.newsArr.map((n,index) => {
return <div key={index} className="news">{n}</div>
})
}
</div>)
}
}
ReactDOM.render(<Father />,document.getElementById('text'))
</script>
</body>
</html>