组件的生命周期
React中组件有生命周期,也就是说也有很多钩子函数供我们使用, 组件的生命周期,我们会分为四个阶段,初始化、运行中、销毁、错误处理(16.3之后)
初始化
在组件初始化阶段会执行
- constructor
- static getDerivedStateFromProps()
- componentWillMount() / UNSAFE_componentWillMount()
- render()
- componentDidMount()
初始化详解
注意:
不写方法的触发( 订阅 )
不写具有副作用的代码( 比如: 计时器 )
这些应当使用componentDidMount()
4. 代码如下:
constructor( props ){
super( props ) //通过super来继承父类身上传递过来的属性,然后当前组件通过this.props接收
this.state = {
money : 10000 //用来初始化一个状态
}
this.change = this.change.bind(this) //初始化绑定一个方法,将this传递给这个方法
}
-
`componentWillMount() 挂载前
- 提供一次数据修改的机会(可以进行数据修改)
- 进行数据请求 axios和fetch
- 注意: 虽然我们这里可以进行数据请求和初始化数据的修改,但是官方建议我们写在componentDidMount中,可以减少副作用和订阅
- 代码如下:
componentWillMount () { // 组件挂载前
this.setState({ // 提供了一次 数据修改机会
money : 30000
})
fetch( '/data.json' ) // 进行数据请求
.then( res => res.json() )
.then( data => console.log( 'componentWillMount' , data ) )
.catch( error => {
if (error) throw error
})
//虽然我们这里可以进行数据请求和初始化数据的修改,但是官方建议我们写在componentDidMount中可以减少副作用和订阅
}
-
`render()
- render()方法是必需的。被调用时,它将计算
this.props
和this.state
,并返回以下一种类型:- React元素。通过jsx创建,既可以是dom元素,也可以是用户自定义的组件。
- 字符串或数字。他们将会以文本节点形式渲染到dom中。
- Portals。react 16版本中提出的新的解决方案,可以使组件脱离父组件层级直接挂载在DOM树的任何位置。
- null,什么也不渲染
- 布尔值。也是什么都不渲染。
- render()
方法必须是一个纯函数,他不应该改变
state`,也不能直接和浏览器进行交互,应该将事件放在其他生命周期函数中。 - 如果
shouldComponentUpdate()
返回false
,render()
不会被调用。 - 代码如下:
- render()方法是必需的。被调用时,它将计算
return 'aaa' //字符串或数字。他们将会以文本节点形式渲染到dom中。
return( //React元素。通过jsx创建,既可以是dom元素,也可以是用户自定义的组件
<Fragment>
<p> 标签 </p>
</Fragment>
componentDidMount () { // 组件挂载完成
this.setState({ // 数据修改
money : 30000
})
fetch( '/data.json' ) // 进行数据请求
.then( res => res.json() )
.then( data => console.log( 'componentDidMount' , data ) )
.catch( error => {
if (error) throw error
})
//重点:: 数据请求和数据修改最好写在componentDidMount中
}
-
`static getDerivedStateFromProps(nextProps , prevState) derived — /dɪ’raɪvd/
static getDerivedStateFromProps
react16.3新增 功能与componentWillMount
相同- 可以数据请求和数据的修改
- 代码如下:
static getDerivedStateFromProps (nextProps, prevState) {
console.log( 'nextProps', nextProps ) //将来的属性
console.log( 'prevState', prevState ) //变化前的值
return {
money: 4000
}
}
更新阶段
-
componentWillReceiveProps(nextProps) 属性发生改变 receive — /rɪ’siːv/
- 触发条件: 属性发生改变,就会触发
- 接收一个参数: 属性变化之后的值
这个钩子函数一定能监听到整个当前组件的属性变化 — > 当前组件的路由我们也可以监听到 - 应用:路由监听
- 代码如下:
componentWillReceiveProps ( nextProps ) {
console.log( 'componentWillReceiveProps ');
console.log( nextProps );//属性变化之后的值
}
-
shouldComponentUpdate() should - - /ʃəd;/
-
决定了组件是否更新
返回值true,更新
返回值false,不更新不书写该钩子时–默认值是true 书写之后必须设置true或false
这个钩子是React性能优化的关键钩子
-
-
componentWillUpdate() 组件即将更新
- 组件即将更新–生成新的VDOM
-
getSnapshotBeforeUpdate() Snap ---- /snæp/
- getSnapshotBeforeUpdate()被调用于render之后,
- 可以读取但无法使用DOM的时候。
- 它使您的组件可以在可能更改之前从DOM捕获一些信息(例如滚动位置)。
- 此生命周期第3个参数传递给componentDidUpdate()。
-
componentDidUpdate() 组件更新完成
-
数据请求
-
DOM操作 ----在componentDidUpdate中可以获取到DOM元素
-
接收
getSnapshotBeforeUpdate()
第三个参数作为返回值使用fiber算法进行 新vdom和旧的vdom对比,生成新的patch对象
再根据patch对象进行页面渲染 -
代码如下:
-
componentDidUpdate ( ) {
fetch( '/data.json' ) //数据请求
.then( res => res.json())
.then( data => console.log( 'componentDidUpdate',data ))
.catch( error => {
if( error ) console.log( error )
})
document.querySelector('h3').style.background = 'red' //DOM操作,做一些第三方库的实例化
console.log( 'componentDidUpdate' )
}
销毁阶段
-
componentWillUnMount() 组件销毁
两种方式:
- 外部销毁:通过开关
- 内部销毁:
ReactDOM.unmountComponentAtNode( document.querySelector('#root') ) //必须是root
错误处理阶段
总结:
- React16新的生命周期弃用了componentWillMount、componentWillReceivePorps,componentWillUpdate
- 新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来代替弃用的三个钩子函数(componentWillMount、componentWillReceivePorps,componentWillUpdate)
- React16并没有删除这三个钩子函数,但是不能和新增的钩子函数(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17将会删除componentWillMount、componentWillReceivePorps,componentWillUpdate
- 新增了对错误的处理(componentDidCatch)