理解
- 组件从创建到死亡它会经历一些特定的阶段
- React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用
- 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作
引出生命周期函数
案例:让指定的文本做显示 / 隐藏的渐变动画,点击“不活了”按钮从界面中卸载组件
效果图:
<script type="text/babel">
// 创建组件
// 生命周期回调函数 <=> 生命周期子函数 <=> 生命周期函数 <=> 生命周期钩子
class Life extends React.Component{
state = {
opacity:1
}
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
// 组件挂载完毕
componentDidMount(){
this.timer = setInterval(() => {
// 获取原状态
let {opacity} = this.state
// 减少0.1
opacity -= 0.1
if(opacity <= 0) opacity = 1
// 设置透明度
this.setState({opacity})
},200)
}
// 组件将要卸载
componentWillUnmount(){
// 清楚定时器
clearInterval(this.timer)
}
// 组件初始化渲染 状态更新之后
render(){
return (
<div>
<h2 style={{opacity:this.state.opacity}}>React学不会怎么办?</h2>
<button onClick={this.death}>不活了</button>
</div>
)
}
}
ReactDOM.render(<Life />,document.getElementById('test'))
</script>
旧版生命周期函数
案例:点击按钮进行不断的加,测试控制台输出的生命周期函数
效果图:
class Count extends React.Component{
constructor(props){
console.log('Count---constructor')
super(props)
// 初始化状态
this.state = {count:0}
}
// 加1按钮的回调
add = () => {
// 获取原状态
let {count} = this.state
// 更新状态
this.setState({count:count+1})
}
// 卸载组件的回调
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
// 强制更新组件的回调
force = () => {
this.forceUpdate()
}
// 组件将要挂在的钩子
componentWillMount(){
console.log('Count---componentWillMount')
}
// 组件挂在完毕的钩子
componentDidMount(){
console.log('Count---componentDidMount')
}
// 组件将要卸载的钩子
componentWillUnmount(){
console.log('Count---componentWillUnmount')
}
// 控制组件更新的 "阀门"
shouldComponentUpdate(){
console.log('Count---shouldcomponentUpdate')
return true
}
// 组件将要更新的钩子
componentWillUpdate(){
console.log('Count---componentWillUpdate')
}
// 组件更新完毕的钩子
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>
)
}
}
ReactDOM.render(<Count />,document.getElementById('test'))
父子组件:
案例:在A组件中使用B组件,B组件渲染A组件的数据,看输出的生命周期钩子
效果图:
// 父组件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{
// 组件将要接收新的props钩子
componentWillReceiveProps(props){
console.log('B---componentWillReceiveProps',props)
}
// 控制组件更新的“阀门”
shouldComponentUpdate(){
console.log('B---shouldComponentUpdate')
return true
}
// 组件将要更新的钩子
componentWillUpdate(){
console.log('B---componentWillUpdate')
}
// 组件更新完毕的钩子
componentDidUpdate(){
console.log('B---componentDidUpdate')
}
render(){
console.log('B---render')
return (
<div>
<div>我是B组件,接收到的车是:{this.props.carName}</div>
</div>
)
}
}
ReactDOM.render(<A />,document.getElementById('test'))
总结:
- 初始化阶段:由
ReactDOM.render()
触发 – 初次渲染constructor()
componentWillMount()
render()
componentDidMount()
常用,一般在钩子中做一些初始化的事,例如:开启定时器,发送网络请求,订阅消息
- 更新阶段:由组件内部
this.setState()
或父组件render
触发shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
- 卸载组件:由
ReactDOM.unmountComponentAtNode()
触发componentWillUnmount()
常用,一般在这个钩子中做一些收尾的事,例如:关闭定时器,取消订阅消息
新版生命周期函数
class Count extends React.Component{
constructor(props){
console.log('Count---constructor')
super(props)
// 初始化状态
this.state = {count:0}
}
// 加1按钮的回调
add = () => {
// 获取原状态
let {count} = this.state
// 更新状态
this.setState({count:count+1})
}
// 卸载组件的回调
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
// 强制更新组件的回调
force = () => {
this.forceUpdate()
}
// 若state的值任何时候都取决于props,那么可以使用getDerivedStateFromProps
static getDerivedStateFromProps(props,state){
console.log('Count---getDerivedStateFormProps',props,state)
// return {count:199} // 会影响state更新
// return props
return null
}
// 在更新之前获取快照
getSnapshotBeforeUpdate(){
console.log('Count---getSnapshotBeforeUpdate')
// return null
return 'atguigu' // 返回的快照值,可以在componentDidUpdate接收到
}
// 组件挂在完毕的钩子
componentDidMount(){
console.log('Count---componentDidMount')
}
// 组件将要卸载的钩子
componentWillUnmount(){
console.log('Count---componentWillUnmount')
}
// 控制组件更新的 "阀门"
shouldComponentUpdate(){
console.log('Count---shouldcomponentUpdate')
return true
}
// 组件更新完毕的钩子
componentDidUpdate(preProps,preState,snapshotValue){
console.log('Count---componentDidUpdate',preProps,preState,snapshotValue)
}
// 组件初次渲染 更新状态的钩子
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>
)
}
}
ReactDOM.render(<Count count={198} />,document.getElementById('test'))
总结:
- 初始化阶段:由
ReactDOM.render()
触发 — 初次渲染constructor()
getDerivedStateFormProps()
render()
componentDidMount()
- 更新阶段:由
组件内部this.setState()
或父组件重新render
触发getDerivedStateFormProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
- 卸载组件:由
ReactDOM.unmountComponentAtNode()
触发componentWillUnmount()
重要的勾子
- 1.render:初始化渲染或更新渲染调用
- 2.componentDidMount:开启监听, 发送ajax请求
- 3.componentWillUnmount:做一些收尾工作, 如: 清理定时器
即将废弃的勾子
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用