开始学习React啦(三)

462 阅读3分钟

一、组件生命周期

所谓的生命周期就是指某个事物从开始到结束的各个阶段,当然在 React 中指的是组件从创建到销毁的过程

在这个过程中的不同阶段调用的函数,即生命周期本质就是一个函数,到了特定时机会自动执行

通过这些函数,我们可以更加精确的对组件进行控制

下面通过一张生命周期流程图进行一个分析

我们可以将生命周期分成两个阶段:

  • 挂载阶段
  • 更新阶段
  • 卸载阶段

挂载阶段

挂载阶段指的是组件创建的虚拟DOM,生成真实DOM,添加到我们指定的DOM节点中

涉及到生命周期有:

  • constructor

  • static getDerivedStateFromProps(props)

  • render

  • componentDidMount

constructor

即组件对象实例化阶段,常用于初始化数据(定义组件state与得到外部传入的props

注意不能在里面使用this.setState

class App extentd App{
    constructor(props){
        this.setate = {}
    }
}

也不要将props数据赋值给state

constructor(props) {
 super(props);
 // 不要这样做
 this.state = { color: props.color };
}

如此做毫无必要(你可以直接使用 this.props.color),同时还产生了 bug(更新 prop 中的 color 时,并不会影响 state)

getDerivedStateFromProps(props)

从命名我们就得知,将传入的props映射到state上面

如果传入的内容不需要影响到组件的state,那么就需要返回一个null

class App extentd App{
    constructor(props){
        super(props)
        this.setate = {}
    }
    static getDerivedStateFromProps(nextProps, prevState) {
        const {type} = nextProps;
        // 当传入的type发生变化的时候,更新state
        if (type !== prevState.type) {
            return {
                type,
            };
        }
        // 否则,对于state不进行任何操作
        return null;
    }
}

componentDidMount

组件挂载完成阶段,这时候页面真实DOM节点已经完成,我们可以进行一些副作用操作,如请求数据,或者获取真实DOM结构

componentDidMount(){
    this.loadData()  // 异步加载数据
}

render函数

render函数用于将VDOM生成真实DOM,是组件必须实现的方法

render(){
    return (
        <input  type="text" defaultValue={inputValue} />
    )
}

更新阶段

更新阶段主要为组件state数据发生变化,需要重新渲染,主要有如下:

  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
  • componentDidUpdate

这里主要讲述getSnapshotBeforeUpdatecomponentDidUpdate这两个生命周期

getSnapshotBeforeUpdate

该生命周期代替componentWillUpdate

特点

  • 读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的

  • 返回的任何值都将作为参数传递给componentDidUpdate

getSnapshotBeforeUpdate(){
    return {foo:'foo'}
}

componentDidUpdate(prevProps, prevState,a){
    console.log(a)  // {foo:'foo'}
}

componentDidUpdate

可以拿到更新前的props和state,并且第三个参数能拿到getSnapshotBeforeUpdate返回的值

组件已经挂载完成,这时候stateDOM都是最新的

componentDidUpdate(prevProps, prevState,snapshot){
    console.log(snapshot)  // {foo:'foo'}
}

不要直接componentDidUpdate中调用this.setState,应该在判断语句if当中,否则会造成无限更新情况

componentDidUpdate(prevProps, prevState,snapshot){
    console.log(snapshot)  // {foo:'foo'}
}

二、受控组件与非受控组件

一句话讲,受控组件指的是将组件的内部状态与state保持一致

<input type"text" value={inputValue}/>

这时候在标签内输入值,我们会发现input标签的值并不会显示,原因是value值已经时刻被inputValue赋予了,inputValue值并没有发生变化

下面通过onChange事件修改inputValue值,从而实现控制组件的内部状态

<input
    type="text"
    value={inputValue}
    onChange={({ target }) => {
        this.setState({
            inputValue: target.value
        })
    }} />

下面再来讲讲非受控组件,其无非也就是不与state产生关联

非受控组件如果想要设置初始值可以通过defaultValuedefaultChecked设置值

<input  type="text" defaultValue={inputValue} />