react组件的生命周期

2,050 阅读3分钟

组件是一个类,当它被使用的时候实例化,然后挂载到页面中。

1.组件第一次加载

组件第一次加载生命周期的执行顺序:

  • defaultProps
  • constructor
  • componentWillMount
  • render
  • componentDidMount
export default class Counter extends Component {
    //如果传递值了使用传递值,没有传值使用默认值:默认属性对象
    static defaultProps = {
        count: 0
    }
    constructor(props) {
        console.log('constructor');
        super(props);
        this.state = { count: props.count };//初始化默认状态对象
    }
    componentWillMount() {
        console.log('1.组件将要挂载 componentWillMount');
    }
    render() {
        console.log('2.render 挂载');
        return (
            <div>
                父计数器:{this.state.count}
            </div>
        )
    }
    //组件挂载完成
    componentDidMount() {
        console.log('3.componentDidMount 组件挂载完毕');
    }
}

输出

constructor
1.组件将要挂载 componentWillMount
2.render 挂载
3.componentDidMount 组件挂载完毕

2.修改状态

添加一个button按钮去修改计数器的state,查看状态更新后组件声明周期的流程

  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate
export default class Counter extends Component {
    //如果传递值了使用传递值,没有传值使用默认值:默认属性对象
    static defaultProps = {
        count: 0
    }
    constructor(props) {
        console.log('constructor');
        super(props);
        this.state = { count: props.count };//初始化默认状态对象
    }
    componentWillMount() {
        console.log('1.组件将要挂载 componentWillMount');
    }
    
    //当需要旧状态时,使用传入一个方法,参数为旧状态这种形式
    handleClick = () => {
        this.setState(prevState => ({
            count: prevState.count + 1
        }));
    }
    
    //询问组件是否要被更新,当一个组件的属性或者状态只要有一个发生了改变 ,默认就会重新渲染。返回true则组件更新,返回false则组件不更新
    shouldComponentUpdate(nextProps, nextState) {
        if (nextState.count < 10) {
            return true;
        } else {
            return false;
        }
    }
    
    componentWillUpdate() {
        console.log('componentWillUpdate');
    }
    componentDidUpdate() {
        console.log('componentDidUpdate');
    }
    
    render() {
        console.log('2.render 挂载');
        return (
            <div>
                父计数器:{this.state.count}
                <button onClick={this.handleClick}>+</button>
            </div>
        )
    }
    //组件挂载完成
    componentDidMount() {
        console.log('3.componentDidMount 组件挂载完毕');
    }
}

输出

constructor
1.组件将要挂载 componentWillMount
2.render 挂载
3.componentDidMount 组件挂载完毕
componentWillUpdate
2.render 挂载
componentDidUpdate

3.接收新的属性

组件内属性不可以更改,只能通过父组件传递。

父组件:

export default class Counter extends Component {
    //如果传递值了使用传递值,没有传值使用默认值:默认属性对象
    static defaultProps = {
        count: 0
    }
    constructor(props) {
        console.log('constructor');
        super(props);
        this.state = { count: props.count };//初始化默认状态对象
    }
    componentWillMount() {
        console.log('1.组件将要挂载 componentWillMount');
    }
    handleClick = () => {
        this.setState(prevState => ({
            count: prevState.count + 1
        }));
    }
    //询问组件是否要被更新,当一个组件的属性或者状态只要有一个发生了改变 ,默认就会重新渲染
    shouldComponentUpdate(nextProps, nextState) {
        if (nextState.count < 10) {
            return true;
        } else {
            return false;
        }
    }
    componentWillUpdate() {
        console.log('componentWillUpdate');
    }
    componentDidUpdate() {
        console.log('componentDidUpdate');
    }
    render() {
        console.log('2.render 挂载');
        return (
            <div>
                父计数器:{this.state.count}
                <button onClick={this.handleClick}>+</button>
                //添加子组件 传递count属性
                <SubCounter count={this.state.count} />
            </div>
        )
    }
    //组件挂载完成
    componentDidMount() {
        console.log('3.componentDidMount 组件挂载完毕');
    }
}

子组件

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • componentDidUpdate
class SubCounter extends Component {
    //当子组件将要接收到父组件传给它的新属性的时候
    componentWillReceiveProps() {
        console.log('SubCounter componentWillReceiveProps');
    }
    shouldComponentUpdate(nextProps, nextState) {
        console.log('SubCounter shouldComponentUpdate');
        if (nextProps.count <= 5) {
            return true;
        } else {
            return false;
        }
    }
    componentWillUpdate() {
        console.log('SubCounter componentWillUpdate');
    }
    componentDidUpdate() {
        console.log('SubCounter componentDidUpdate');
    }
    render() {
        console.log('SubCounter render 挂载');
        return (
            <div>
                子计数:{this.props.count}
            </div>
        )
    }
}

未点击加号输出:

constructor
1.组件将要挂载 componentWillMount
2.render 挂载
SubCounter render 挂载
3.componentDidMount 组件挂载完毕   //需要子组件加载完毕后父组件才会加载完毕

点击添加按钮 新增输出:
//先是父组件将要更新,然后渲染
componentWillUpdate
2.render 挂载
//子组件
SubCounter componentWillReceiveProps
SubCounter shouldComponentUpdate
SubCounter componentWillUpdate
SubCounter render 挂载
SubCounter componentDidUpdate
//父组件完成更新
componentDidUpdate

4.组件的卸载

什么时候用到componentWillUnmount:

单页应用中,切换页面原组件需要销毁释放资源,如果原组件中有定时器等不能销毁时,需要在componentWillUnmount中清理资源占用,手动销毁定时器。

export default class Counter extends Component {
    //默认属性对象
    static defaultProps = {
        count: 0
    }
    constructor(props) {
        console.log('constructor');
        super(props);
        this.state = { count: props.count };//初始化默认状态对象
    }
    componentWillUnmount() {
        window.clearInterval(this.timer);
        console.log('componentWillUnmount');
    }
    destroy = () => {
        //卸载组件的方法
        ReactDOM.unmountComponentAtNode(document.querySelector('#root'));
    }
    render() {
        return (
            <div>
                父计数器:{this.state.count}
                <button onClick={this.destroy}>destroy</button>
            </div>
        )
    }
    //组件挂载完成
    componentDidMount() {
        console.log('3.componentDidMount 组件挂载完毕');
       //如果不清定时器,组件卸载将要报错,因为组件卸载this这个当前组件已被销毁。
        this.timer = window.setInterval(() => {
            this.setState(prevState => ({
                count: prevState.count + 1
            }));
        }, 1000);
    }
}