react-生命周期超详细讲解

首先,我们来看一张官方的生命周期图

在这里插入图片描述
很多人,看到这张图的时候,都是一脸懵逼的,因为他是把所有生命周期所出现的所有场景整合在一起的,初学者难免会有点混乱,接下来,我会通过代码加场景,跟大家一一的过一遍。

挂载过程

1.constructor()
react的初始化函数,它完成了react数据的初始化,接受一个props参数,如果想要在constructor函数中使用父组件传递过来的props的时候,就需要在super里面传递这个参数。
在我的另外一篇关于constructor的文章中也提到了,如果不定义constructor的话,class会默认生成一个,但是如果定义了,需要在页面中使用this的时候,就需要constructor中调用super,而如果在constructor需要用到props,那么久需要把props当初参数传递给super()

2.componentWillMount()

组件经过了constructor初始化函数,数据将要挂载的时候触发,要注意,此时dom元素还没有渲染,在这个函数里面使用refs,是拿不到dom元素的

3.render
渲染组件的函数,在这个函数里会把初始化好的数据,渲染到组件里面。每一次数据更新的时候,这个函数就会执行一遍。
即:当组件的state或者props发生改变的时候,render函数就会重新执行
当父组件的render函数被运行时,它的子组件的render都将被重新运行一次
所以为了性能上的优化,render里面,尽量不要写逻辑操作。当然也不能在这个函数里面修改state数据,否则就会陷入死循环(state初始化–>触发render–>render修改state–>state改变–>触发render–>render修改state…)

4.componentDidMount()

组件挂载完成的时候触发,此时dom元素已经生成。我们一般都会在这个函数里面调用ajax函数

总体代码如下

export default class Test extends Component {
    constructor() {
        super()
        console.log("第一步,构造函数")
    }
    componentWillMount() {
        console.log("第二步,组件将要被挂载")
    }
    render() {
        console.log("第三步,组件被挂载")
        return (
            <div>
                
            </div>
        )
    }
    componentDidMount() {
        console.log("第四步,组件挂载完成")
    }
}

控制台

第一步,构造函数
第二步,组件将要被挂载
第三步,组件被挂载
第四步,组件挂载完成

组件更新过程

1.shouldComponentUpdate
是否要更新数据。
这个函数返回一个布尔值,
如果返回true,表示 可以更新数据,函数就可以往下执行,即可以继续执行componentWillUpdate和render和componentDidUpdate
返回false,就不更新数据,那么在这个函数后面的生命周期函数,就不会执行

这个函数还接收两个参数,nextProps以及nextState,即更新后的父组件传过来的值以及更新后的state的值

因为,我们可以在这个生命周期里面,做性能优化:比较一下更新后的nextState的值,与原来的state的值是否一致,如果是一致的,那么就返回false,即不继续向下执行,不重新更新render

2.componentWillUpdate
函数将要被更新的时候触发,这个函数用的不多

3.componentDidUpdate
函数更新完成之后触发,如果我们需要更新完成某些数据之后,再执行某些操作,就可以写在这个函数里面

总体代码如下

export default class Test extends Component {
  constructor() {
    super()
    this.state = {
      msg: 111
    }
  }
  handleChangeMsg = () => {
    this.setState({
      msg: 222
    })
  }
  render() {
    console.log("组件渲染")
    return (
      <div>
        <div>{this.state.msg}</div>
        <button onClick={this.handleChangeMsg}>修改数据</button>
      </div>
    )
  }
  shouldComponentUpdate(nextProps, nextState) {
    console.log("是否更新组件")
    console.log(nextProps, nextState)
    return true // 如果这里是return false,那么componentWillUpdate,componentDidUpdate,render函数,都不会执行
  }
  componentWillUpdate(nextProps, nextState) {
    console.log("组件将要被更新")
    console.log(nextProps, nextState)
  }
  componentDidUpdate(prevProps, prevState) {
    console.log("组件更新完成")
    console.log(prevProps, prevState)
  }
}

控制台

是否更新组件
{} {msg: 222}
组件将要被更新
{} {msg: 222}
组件渲染
组件更新完成
{} {msg: 111}

可以看到,shouComponentUpdate和componentWillUpdate的两个参数,都是更新前的值,而componentDidUpdate的两个参数,都是更新后的值

componentWillReceiveProps和componentWillUnmount

先说说componentWillUnmount,也就是组件被销毁的时候触发。如

// 父组件
import ChildrenTest from "./childrenTest"
export default class App extends Component {
  constructor() {
    super()
    this.state = {
      isShowChildrenTest: true
    }
  }
  handleUnmount = () => {
    this.setState({
      isShowChildrenTest: false
    })
  }
  render() {
    return (
      <div>
        {this.state.isShowChildrenTest ? <ChildrenTest></ChildrenTest> : ""}
        <button onClick={this.handleUnmount}>销毁组件</button>
      </div>
    )
  }
}

//子组件
export default class childrenTest extends Component {
    render() {
        return (
        <div>childrenTest</div>
        )
    }
    componentWillUnmount() {
        console.log("我被销毁了")
    }
}

当点击父组件的“销毁组件”按钮的时候,变量isShowChildrenTest变成了false,那么子组件就被销毁了,此时子组件的componentWillUnmount就触发了

我们再来看看 componentWillReceiveProps,组件从父组件接收参数,且父组件的render函数重新执行的时候,这个函数会执行。(如果这个组件是第一次存在于父组件中,不会执行,如果这个组件之前就存在于父组件中,会执行。),他接收一个参数nextProps,是不是很熟悉,因为他跟shouldComponentUpdate的参数nextProps是一样的,是改变后的props。
我们可以把父组件传递过来的props赋值给子组件本身的state,因为react是不允许子组件去修改父组件的值,但是可以修改自身的state。

//父组件
export default class App extends Component {
  constructor() {
    super()
    this.state = {
      faMsg: "父组件的msg"
    }
  }
  handleChangeFaMsg = () => {
    this.setState({
      faMsg: "父组件的msg的值改变了"
    })
  }
  render() {
    return (
      <div>
        <ChildrenTest faMsg={this.state.faMsg}></ChildrenTest> 
        <button onClick={this.handleChangeFaMsg}>修改父组件的值</button>
      </div>
    )
  }
}

//子组件
export default class childrenTest extends Component {
    constructor(props) {
        super(props)
        this.state = {
            faMsg: ""
        }
    }
    render() {
        return (
            <div>{this.props.faMsg}</div>
        )
    }
    componentWillReceiveProps(nextProps) {
        console.log(nextProps)
        this.setState({
            faMsg: nextProps.faMsg
        })
    }
}

当父组件传递给子组件的props发生改变的时候,我们对应的也同步修改state的值。
然后在子组件中,我们就可以操作这个父组件传递过来的值了(不过不建议这样做,因为为了保证数据一致性,不应该在子组件中修改父组件传递过来的值,如果想要修改,应该在子组件中去调用父组件的某个方法去修改父组件的值)

componentWillUnmount:

会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除定时器,取消网络请求或清除在 componentDidMount() 中创建的订阅,清理无效的DOM元素等垃圾清理工作。

到这里就结束辣,在最新的react版本中,类似于componentWillMount之类的函数,已经慢慢的被废除了,需要了解的小伙伴们,可以自行上react的官网查阅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值