React16.3后的生命周期理解

可以直接拷贝这段代码,然后执行打开控制台查看生命周期的流程。

注意:默认情况下使用了新的生命周期后,老的生命周期不会去执行。会在控制台报警告

//ComponentLifeCycle

import React, { Component } from 'react';

export default class ComponentLifeCycle extends Component {
    constructor(props) {
        super(props)
        this.state = {
            title: '默认文本',
            flagCount: Number(0),
            value: ''
        }
        //新的ref绑定方法
        this.inputRef = React.createRef();
        this.textRef = React.createRef();
    }


    // 组件将要挂载的时候调用

    UNSAFE_componentWillMount() {
        console.log('componentWillMount:\n只在第一次render之前调用一次')
        //对于某些操作比如说在willMount的时候去调接口的话 请将异步逻辑移步到componentDidMount生命周期
        //接口请求放在这里和即将到来的异步呈现模式冲突(其中请求可能被多次启动)
        //如果在willMount的时候想要把props的某些属性赋值给state状态机  请将此类操作直接在构造函数中进行
        setTimeout(() => {
            this.setState({
                title: 'componentWillMount'
            })

        }, 1500)
    }

    // 当props发生变化时执行,初始化render时不执行,
    // 在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,
    // 旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用

    UNSAFE_componentWillReceiveProps(nextProps, props) {
        if (nextProps !== this.props) {
            setTimeout(() => {
                this.setState({
                    title: 'componentWillReceiveProps'
                })
                console.log('componentWillReceiveProps:', '\n新的props', nextProps, '\n老的props', props)
            }, 1500)
        }

    }

    // 组件将要跟新的时候触发,即state树发生变化时触发
    // 在异步模式下使用componentWillUpdate都是不安全的,因为外部回调可能会多次调用只更新一次

    UNSAFE_componentWillUpdate(nextProps, nextState) {
        setTimeout(() => {
            console.log('componentWillUpdate:', '\n新的state', nextState, '\n新的props', nextProps)
        }, 1500)
    }

    // 组件更新结束之后执行,在初始化render时不执行
    componentDidUpdate(prevProps, prevState) {
        // 如果不在此处限制条件的话 DidUpdate生命周期后会不断执行
        if (this.state.flagCount < 1) {
            setTimeout(() => {
                this.setState({
                    title: 'componentDidUpdate',
                    flagCount: this.state.flagCount + 1
                })
                console.log('componentDidUpdate:\n之前的props', prevProps, '\n之前的state', prevState, '\n更新后的state', this.state)
            }, 1500)

        }
    }
    // 组件第一次加载完成 
    // 在这里调用接口数据请求和进行事件监听
    // 有一个常见的错误观念认为,在componentWillMount中提取可以避免第一个空的渲染。
    // 在实践中,这从来都不是真的,因为React总是在componentWillMount之后立即执行渲染。
    // 如果数据在componentWillMount触发的时间内不可用,则无论你在哪里提取数据,第一个渲染仍将显示加载状态。
    // 这就是为什么在绝大多数情况下将提取移到componentDidMount没有明显效果。
    componentDidMount = () => {
        setTimeout(() => {
            this.setState({
                title: 'componentDidMount',
            })
            console.log('componentDidMount')
        }, 1500)
    };

    // 组件卸载后执行
    // 人们经常认为componentWillMount和componentWillUnmount总是配对,但这并不能保证。
    // 只有调用componentDidMount后,React才能保证稍后调用componentWillUnmount进行清理。
    // 出于这个原因,添加事件监听的推荐方式是使用componentDidMount生命周期:

    //如果想要添加事件监听函数,请移步到componentDidMount生命周期,
    //在这里添加的话会导致服务器渲染(componentWillUnmount永远不会被调用)
    //异步渲染(在渲染完成之前渲染可能被中断,
    //导致componentWillUnmount不被调用)的内存泄漏。
    componentWillUnmount() {
        this.setState({
            title: 'componentWillUnmount'
        })
        console.log('componentWillUnmount ')
    }
    // 新的静态getDerivedStateFromProps生命周期在组件实例化以及接收新props后调用。
    // 它可以返回一个对象来更新state,或者返回null来表示新的props不需要任何state更新。
    // 与componentDidUpdate一起,这个新的生命周期应该覆盖传统componentWillReceiveProps的所有用例。
    static getDerivedStateFromProps(nextProps, prevState) {
        console.log('getDerivedStateFromProps', nextProps, prevState)
        if (nextProps.value !== prevState.value) {
            return {
                value: nextProps.value
            }
        }
        return null
    }

    // 新的getSnapshotBeforeUpdate生命周期在更新之前被调用(例如,在DOM被更新之前)。
    // 此生命周期的返回值将作为第三个参数传递给componentDidUpdate。 
    //(这个生命周期不是经常需要的,但可以用于在恢复期间手动保存滚动位置的情况。
    // 与componentDidUpdate一起,这个新的生命周期将覆盖旧版componentWillUpdate的所有用例
    getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log('getSnapshotBeforeUpdate', prevProps, prevState)
        return null
    }

    render() {
        setTimeout(() => {
            console.log('render')
        }, 1500)
        return [
            this.state.flagCount == 1 ?
                [
                    <input key="input" style={{width:200}} type="text" placeholder="我是新的ref属性绑定方法的input" ref={this.inputRef} />,
                    <input key="inputbefore" style={{width:300}} type="text" placeholder="早前绑定ref使用回调:node=>this.input=node" ref={node=>this.inputBefore=node} />,
                    <p key="p" ref={this.textRef}>我是一段文本,ref属性绑定的是this.textRef</p>,
                    <h1 key="0">{this.state.flagCount}</h1>,
                    <div key="1">当前生命周期: {this.state.title}</div>,
                    <div key="2">{this.props.value}</div>,
                    <button key="3" onClick={this.props.click}>点击模拟更新props</button>,
                    <button key="4" onClick={_=>this.inputRef.current.focus()}>点击让input获得焦点</button>,
                    <button key="6" onClick={_=>console.log(this.textRef)}>打印文本ref对象</button>
                ]:<p key="5">loading.....</p>

        ]
    }
}



父组件引用的地方:

import ComponentLifeCycle from './componentlife'

export default class Test extends Component {
    state = {
        count: 0
    }
    count = () => {
        if (this.state.count < 20) {
            this.setState({
                count: this.state.count + 1
            })
        }
    };

    render() {
        return [
            <ComponentLifeCycle
                key="0"
                value={this.state.count}
                click={this.count}
            />,
        ]
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值