第二章 react生命周期

本文详细解析了React组件的生命周期,包括装载、更新和卸载三个阶段的关键方法。通过具体实例介绍了如何利用这些生命周期方法进行组件的状态管理和性能优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生命周期

在这里插入图片描述

装载过程 Mount

组件第一次在dom树中渲染的过程

constructor

无状态的组件,则不需要定义构造函数,一个组件需要构造函数,往往是以下的目的:

  • 初始化state
  • 绑定函数的this环境
this.foo = ::this.foo
# 等价
this.foo = this.foo.bind(this)
getInitialState

返回值会用来初始化组件的this.state 只用React.createClass方法创造的组件

getDefaultProps

返回值会作为props的初始值 只用React.createClass方法创造的组件

componentWillMount

所有可以在这个中做的事情,都可以提前到constructor中间去做;可以在服务器端被调用,也可以在浏览器端被调用

render

render 函数并不做实际的渲染动作,它只返回一个jsx描述的结构,最终由react来操作渲染过程

componentDidMount

render函数被调用完毕后,componentDidMount并不是会被立马调用,而是等render函数返回的东西已经引发了渲染,组件已经被“装载”到了dom树上;只能在浏览器端被调用
【如果需要引用第三方插件(譬如jq),则在这个周期里操作】

import React,{Component} from 'react'

export default class Counter extends Component{
	
	constructor(props){
		console.log('enter constructor '+props.caption)
		super(props);
		this.addNum = this.addNum.bind(this);
		this.decrementNum = this.decrementNum.bind(this);
		this.state = {
			count:props.initValue || 0
		}
	}
	
	addNum(){
		this.setState({
			count:this.state.count+1
		})
	}
	decrementNum(){
		this.setState({
			count:this.state.count-1
		})
	}
	componentWillMount(){
		console.log('enter componentWillMount '+this.props.caption)
	}
	render(){
		const {caption} = this.props;
		console.log('enter render '+this.props.caption)
		return (
				<div>
				<button onClick={this.addNum}>+</button>
				<button onClick={this.decrementNum}>-</button>
				<span>{caption}:{this.state.count}</span>
				</div>
			)
	}
	componentDidMount(){
		console.log('enter componentDidMount '+this.props.caption)
	}
}

在这里插入图片描述

更新过程 Update

组件被重新渲染的过程

componentWillReceiveProps

只要父组件的render函数被调用,在render函数里被渲染的字组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWillReceiveProps。注意通过setState方法触发的更新过程就不会调用这个函数,这个函数适合根据心的props值(nextProps)来计算出是不是要更新内部状态的state。

**注意:**尽量不要直接把用匿名函数赋值给onClick的方法,每次渲染都会创造一个心的匿名方法对象,有可能引发子组件不必要的重新渲染

export default class ControlPanel extends Component{
	constructor (props) {
    super(props)
    this.test = this.test.bind(this)
    this.state = {
        checkboxCheck: true
    }
  }
  test(){
  	this.setState({
        checkboxCheck: !this.state.checkboxCheck
    })
  }
	render(){
		return (
			<div>
				<Counter caption="First" initValue={0} />
				<Counter caption="Second" initValue={10} />
				<Counter caption="Third" initValue={20} />
				<button onClick={this.test} >test {this.state.checkboxCheck}</button>
			</div>
			)
	}
}

在这里插入图片描述

shouldComponentUpdate

参数nextProps nextState, 它决定一个组件什么时候不需要渲染,返回bool值【性能优化】

shouldComponentUpdate(nextProps,nextState){
	return (nextProps.caption!== this.props.caption) ||(nextState.count!==this.state.count)
}

在这里插入图片描述

componentWillUpdate

不论更新过程发生在服务端还是浏览器端,该函数都会被调用

render

同上面的render

componentDidUpdate

执行其他的ui库

卸载过程 Unmount

组件从dom中删除的过程

componentWillUnmount

注意销毁非react方法创造的dom

子组件向父组件传值

通过prop,父组件定义方法,作为属性传递给子组件,子组件执行方法

# counter.js 子组件
    addNum(){
		this.updateCount(true)
	}
	decrementNum(){
		this.updateCount(false)
	}
	updateCount(isAdd){
		const previousValue = this.state.count;
		const newValue = isAdd ? previousValue+1:previousValue-1
		this.setState({
			count:newValue
		})
		this.props.onUpdate(newValue,previousValue)
	}

#ControlPanel.js 父组件
    export default class ControlPanel extends Component{
    	constructor (props) {
        super(props)
        this.test = this.test.bind(this)
        this.state = {
            checkboxCheck: true
        }
    
        this.onCounterUpdate = this.onCounterUpdate.bind(this)
        this.initValues = [0,10,20];
        const initSum = this.initValues.reduce((a,b)=>a+b,0)
        this.state = {
        	sum:initSum
        }
      }
      onCounterUpdate(newVal,preVal){
      	const changeVal = newVal - preVal
      	this.setState({
      		sum:this.state.sum+changeVal
      	})
      }
      test(){
      	this.setState({
            checkboxCheck: !this.state.checkboxCheck
        })
      }
    	render(){
    		console.log('enter ControlPanel render ')
    		return (
    			<div>
    				<Counter onUpdate={this.onCounterUpdate} caption="First" initValue={this.initValues[0]} />
    				<Counter onUpdate={this.onCounterUpdate} caption="Second" initValue={this.initValues[1]} />
    				<Counter onUpdate={this.onCounterUpdate} caption="Third" initValue={this.initValues[2]} />
    				<button onClick={this.test} >test {this.state.checkboxCheck}</button>
    				<div>Total Count: {this.state.sum}</div>
    			</div>
    			)
    	}
    }

but不推荐这样使用,原因:

  • 每个Counter组件都有自己的状态记录当前计数,而父组件也有一个状态来存储所有的子组件计数之和,数据发生了重复
  • 如果数据存在多份,但是不一致,则很难决定使用那些数据

全局状态就是唯一可靠的数据源,为了避免这个问题,下一章将探讨Store

github地址
码云地址
在这里插入图片描述
更多精彩,请关注订阅号韶华随记
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值