React类组件和生命周期浅析

184 阅读3分钟

创建Class组件

import React from 'react'
class B extends React.Component {
    constructor(props) {
        super(props)
    }
    render() {
        return <div>hi</div>
    }
}
export default B

Props(外部数据)

初始化

class B extends React.Component {
// 初始化必须写全套
  constructor(props) {
    super(props);
  }
  render(){}
}

读取 this.props.xxx

class B extends React.Component {
  constructor(props) {
    super(props);
  }
  render(){
    return <div onClick={this.props.onClick}>
      {this.props.name}
      <div>
        {this.props.children}
      </div>
    </div>
}

相关钩子(已经不用了)

// 用来检测props的变化
componentWillReceiveProps(nextProps, nextContext) {
  console.log('props变化了');
}

作用

  1. 接受外部数据

    只能读不能写

    外部数据由父组件传递

  2. 接受外部函数

    在恰当的时机,调用该函数

    该函数一般是父组件的函数

state(内部数据)

初始化

class B extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      user: {name:'frank', age:18}
    }
  }
  render() { /* ... */ }
}

读this.state

// this.state.xxx.yyy
{this.state.user.name}
{this.state.user.age}

写this.setState(???,fn)

this.setState(newState,fn)
this.setState({x: this.state.x + 1})
// 写法二
this.setState((state,props)=>newState,fn) // fn 会在成功后执行回调
// 函数写法
this.setState((state) => ({x: state.x + 1}))

注意setState不会立刻改变this.state,会在当前代码运行完后,再去更新this.state,从而触发UI更新。

在写时:setState会自动将新state与旧state进行一-级合并。

生命周期

官方文档

constructor() -在这里初始化state shouldComponentUpdate() - return false阻止更新 render() -创建虚拟DOM componentDidMount() -组件已出现在页面 componentDidUpdate() -组伴已更新 componentWillUnmount() -组件将死

constructor(初始化)

官方文档

初始化 props

初始化 state

用来写 bind this

render(渲染)

官方文档

用途 展示视图

return (<div>...</div>)  // 虚拟DOM

只能有一个根元素

如果有两个根元素,就要用<React.Fragment>包起

<React.Fragment />可以缩写成<></>

技巧

render里面可以写if.. .else

render(){
  if(this.state.n % 2 ===0){
   return  <div>偶数</div>
  }else {
   return <div>奇数</div>
  }
}

render里面可以写?:表达式

{this.state.n % 2 === 0 ? <div>偶数</div> : <div>奇数</div>}

render里面不能直接写for循环,需要用数组

render里面可以写array.map (循环)

render(){
 return this.state.array.map(n=><div>{n}</div>)
}

componentDidMount(组件已挂载)

官方文档

用途

在元素插入页面后执行代码,这些代码依赖DOM

比如你想获取div的高度,就最好在这里写

此处可以发起加载数据的AJAX请求(官方推荐)

首次渲染会执行此钩子

  componentDidMount() {
    const div = document.getElementById('xxx')
    const {width} = div.getBoundingClientRect()
    this.setState({width})
  }

shouldComponentUpdate(组件是否更新)

官方文档

它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新

返回true表示不阻止UI更新

返回false表示阻止UI更新

  onClick = () => {
    this.setState(state => ({
      n: state.n + 1
    }))
    this.setState(state => ({
      n: state.n - 1
    }))

    // 看似值没有变 但是产生了一个新的对象
  }

  shouldComponentUpdate(nextProps, nextState, nextContext) {
    return nextState.n !== this.state.n;
  }

image-20210409172707071

这个钩子可以采取了内置功能 React.pureComponent

PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。 如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。

class App extends React.pureComponent {
 ...
}

componentDidUpdate(组件已更新)

官方文档

用途

在视图更新后执行代码

此处也可以发起AJAX请求,用于更新数据(看文档)

首次渲染不会执行此钩子

在此处setState可能会引起无限循环,

除非放在if 里

若shouldComponentUpdate返回false,则不触发此钩子

componentWillUnmount(组件将死)

官方文档

用途 组件将要被移出页面然后被销毁时执行代码 unmount过的组件不会再次mount

举例

如果你在componentDidMount里面监听了window scroll,那么你就要在componentWillUnmount里面取消监听

如果你在componentDidMount里面创建了Timer,那么你就要在componentWillUnmount里面取消Timer

如果你在componentDidMount里面创建了AJAX 请求,那么你就要在componentWillUnmount里面取消请求

钩子运动图

image-20210409203947924


资料来源:饥人谷

本文为贰贰的原创文章,著作权归本人和饥人谷所有,转载务必注明来源