生命周期函数

1.生命周期函数

1.1 16版本及以前的

初始化constructor

-->将要渲染componentWillMount

--->已经渲染componentDidMount

--->组件接受传递数据componentWillReceiveProps

----> 是否要更新(shouldComponentUpdate)

---->将要更新componentWillUpdate

---->更新过程render

---->已经更新componentDidUpdate

--->卸载componentWillUnmount

// 组件数据来源 组件本身的状态state(可读可写) 和传递过来props(只读)

/* 
react16生命周期函数:分为三个过程 对应的9个钩子函数
    1 挂载过程 
        constructor(初始化类似于beforeCreate),
        componentWillMount(渲染前,类似于vue的beforeMount)、
        componentDidMount(渲染后,类似于mounted)
    2 更新过程 
        componentWillReceiveProps(将要接受传递数据) 、 
        shouldComponentUpdate(组件是否要更新)、 
        componentWillUpdate(组件将要更新)、
        render(更新过程)、 
        componentDidUpdate(组件更新之后)
    3 卸载过程 componentWillUnmount() 卸载过程
*/

class S1 extends React.Component{  
    constructor(props){
        // 1 组件构造函数 创建组件对象,构造器里面的this就是指向正在创建的组件对象,state在此处进行初始化,不能访问this.props,这个函数执行完之后this.props才会有值,
        console.log("1 组件初始化数据的触发,此处不能访问this.Props")
        super()
        this.state={
            age:10,
            b:""
        }
    }
    //WARNING! To be deprecated in React v17. Use componentDidMount instead.
    componentWillMount() {
        // 不能在此钩子获取DOM节点
        console.log("2 组件将要渲染的时候触发,此处不能获取DOM节点",document.getElementById("d1"))

    }
    componentDidMount() { 
        // 在此处可以获取DOM节点
        console.log("3 组件已经渲染完毕的时候触发",document.getElementById("d1"))
        }


        //WARNING! To be deprecated in React v17. Use new lifecycle static getDerivedStateFromProps instead.
    // 组件将要接受传递数据更新时候触发,需要在此钩子函数里面根据传递的数据是否更新组件(对比更新前后的数据,如果一样了,这时候不需要更新,如果不一样了,需要更新)
    // 如果点击修改sex 如果修改了sex改成了女 是更新,再点击由女变成女 不需要更新
    // nextProps 更新之后的数据
    // this.props 更新之前的数据
        componentWillReceiveProps(nextProps) {
        console.log("4 组件将要接受传递数据触发",nextProps,this.props)
        
        if(nextProps.bool!=this.props.bool){
            // 需要更新 把更新之后数据赋值给本组件的状态b
            this.setState({
                b:nextProps.bool  
            },()=>{
                // b数据更新成功了  setState是一个异步修改
                // 发请求,根据在使用组件的时候传递数据不一样,根据数据发请求或者进行渲染
            })
        }
        }
        shouldComponentUpdate(nextProps, nextState) { 
        console.log("5 组件是否要更新")
        // 
        console.log(this.props.bool,nextProps.bool);
        console.log(this.state.b,nextState.b);
        // 对比组件接收到的状态是否一致,一致不需要更新
        if (this.state.b != nextState.b) return true
        else return false
        }

        //WARNING! To be deprecated in React v17. Use componentDidUpdate instead.
        componentWillUpdate(nextProps, nextState) {
        console.log("6 组件将要更新")
        }

        componentDidUpdate(prevProps, prevState) {
        console.log("7 组件已经更新")
        }

        componentWillUnmount() {
        console.log("8 组件将要卸载")
    }
    render() {
        console.log("render 更新过程")
        return(
            <div id="d1">
                {this.state.age} --{this.state.b}
                
                {
                    /*
                <button onClick={()=>{
                    this.setState({age:100})
                }}>更新age</button>
                    */
                }
                
            </div>
        )
    }
}


class Father extends React.Component{
    constructor(props){
        super()
        this.state = {
            sex:"男"
        }
    }
    render(){
        return(
            <div>
                <button onClick={()=>{
                    this.setState({
                        sex:'女'
                    })
                }}>更改sex---{this.state.sex}</button>
                <S1 bool={this.state.sex}></S1>
            </div>
        )
    }
}

// 16的渲染函数是 参数1渲染的组件 参数2渲染的节点
ReactDOM.render(
    <Father></Father>,
    document.getElementById("app")
)

 1.2 17及以后的生命周期函数

新的钩子函数8个
1 挂载过程 
    constructor(初始化状态)  
    ---componentWillMount(**删除)
    componentDidMount(渲染完毕)
2 更新过程 
    getDerivedStateFromProps(从props更新状态,要有返回对象;返回对象是组件状态的更新 ,与this.setState一样中的对象一样,不要更改的话返回null)(**componentReceivedProps改名)、
    shouldComponentUpdate(是否要更新,需要有返回值是一个布尔值) 、
    getSnapshotBeforeUpdate(组件更新前,要有返回对象,返回值是对象)(**componentWillUpdate改名) 
    render(更新)、
    componentDidUpdate(已经更新)
3 卸载过程 

/* 
新的钩子函数8个
1 挂载过程 
    constructor(初始化状态)  
    componentWillMount(删除)
    componentDidMount(渲染完毕)
2 更新过程 
    getDerivedStateFromProps(从props更新状态,要有返回值)(componentReceivedProps改名)、
    shouldComponentUpdate(是否要更新) 、
    getSnapshotBeforeUpdate(组件更新前,要有返回值)(componentWillUpdate改名) 
    render(更新)、
    componentDidUpdate(已经更新)
3 卸载过程 
    componentWillUnmount 卸载前
*/ 
class S1 extends React.Component{
    constructor(props){
        console.log("1 组件初始化数据的触发")
        super()
        this.state={   
            i1:""
        }
    }
    // react17 以及更高的版本把componentWillMount(将要渲染的钩子函数)写的业务路径放在componentDidMount(以及渲染的钩子函数中)
    // componentWillMount() {}
    componentDidMount() { 
        console.log("2 组件渲染完毕的钩子函数")
        }

    // 更新过程 
    // componentWillReceiveProps(nextProps) {}
        // componentWillReceiveProps 被取代了 替换成了getDerivedStateFromProps(从props获取状态)

    // derived 获取;
    static getDerivedStateFromProps(props, state) {
        console.log("3 组件从props中获取数据时候调用,可以调用的多次,初始化的时候也会调用一次",props,state)
        if(props.id!=state.i1){
            // 当传递数据和当前状态不一样时候,需要把传递数据更新到组件状态上
            // -----------------------------------------------------------
            //  注意:::返回对象是组件状态的更新 ,把状态的i1更新成props.id
            return {
                i1:props.id 
            }
        }
        return null  // 如果传递数据和当前状态一样 不用更新状态
    }

    shouldComponentUpdate(nextProps, nextState) { 
        // nextState 更新之后的状态
        // this.state.i1
        console.log("4 组件是否要更新",nextProps,nextState,this.state)
        // 下面四种方式都可以提升渲染效率
        // if(nextProps.id != this.state.i1){
        if(nextState.i1 != this.props.id){
        // if(nextState.i1 != this.state.i1){ 
        // if(nextProps.id != this.props.id){ 
            return true // true 组件要更新; false 组件不更新
        }
        return false
        
    }
        
    //WARNING! To be deprecated in React v17. Use componentDidUpdate instead. 
    // componentWillUpdate(nextProps, nextState) {}
    // 将要更新的函数componentWillUpdate 被替代了,换成了getSnapshotBeforeUpdate()
    // snapshot 快照
    getSnapshotBeforeUpdate (prevProps, prevState){
        console.log("5 组件在最终更新前触发")
        return null
    }
    componentDidUpdate(prevProps, prevState) {
        console.log("6 组件更新之后触发")
    }
    componentWillUnmount() { 
        console.log("7 组件更将要卸载的时候触发")
    }

    render() {
        return(
            <div id="d1">
                {this.state.i1}
            </div>
        )
    }
}

class Father extends React.Component{
    constructor(props){
        super()
        this.state = {
            id:1
        }
    }
    render(){
        return(
            <div>
                <button onClick={()=>{
                    this.setState({
                        id:2
                    })
                }}>点击修改id--{this.state.id}</button>
                <S1 id={this.state.id}></S1>
            </div>
        )
    }
}

const root = ReactDOM.createRoot(document.getElementById("app")).render(<Father/>)

3 扩展,更改生命周期函数的原因。

componentWillReceiveProps为啥被替换为getDerivedStateFromProps???

因为强制开发者去对比props对象和state对象,而不是直接对比props和this.props,

防止开发者会去操作this.props,组件自身的状态将变得不可预测;

老版本对比this.props和nextProps;新版本使用props传递的数据与state自身定义的状态进行对比;

旧的React中componentWilReceiveProps方法是用来判断前后两个props是否相同,如果不同,则将新的props更新到
相应的state上去。在这个过程中我们实际上是可以访问到当前props的,这样我们可能会对this .props做-些奇奇怪怪的
操作,很可能会破坏state数据的单一数据源, 导致组件状态变得不可预测。
而在getDerivedStateFromProps中禁止了组件去访问this.props,强制让开发者吡较nextProps与prevState 中的值,
以确保当开发者用到getDerivedStateFromProps这个生命周期函数时,就是在根据当前的props来更新组件的state,而
不是去访问this props并做其他一些让组件自身状态变得更加不可预测的事情。
 

那么 componentWillUpdate为什么被改为getSnopshotBeforeUpdate呢??
老版本使用的两个参数是nextProps与nextState进行对比,而componentDidUpdate中是prevProps与prevState;

新版本使用prevProps与prevState,与componentDidUpdate中的prevProps与prevState参数相同;

在React开启异步渲染模式后,在执行函数时读到的DOM元素状态并不总是渲染时相同,这就导致在
componentDidUpdate中使用componentWillUpdate中读取到的DOM元素状态是不安全的,因为这时的值很有可能已经
失效了。
而getSnapshotBeforeUpdate会在最终的render之前被调用,也就是说在getSnapshotBeforeUpdate中读取到的DOM
元素状态是可以保证与componentDidUpdate中-致的。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值