React 学习 第四天

90 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

组件的生命周期

1.概述

  • 意义:组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等
  • 只有类组件才有生命周期

2.生命周期的三个阶段

  1. 创建时(挂载阶段)

    • 执行时机:组件创建时(页面加载时)

    • 执行顺序:

      graph LR
      A(constructor)-->B(render)-->C(componentDidMount)
      
      钩子函数触发时机作用
      constructor创建组件时,最先执行1. 初始化state
      2.为事件处理程序绑定this
      render每次组件渲染都会触发渲染UI(注意:不能调用setState())
      componentDidMount组件挂载(完成DOM渲染)后1. 发送网络请求
      2. DOM操作
  2. 更新时(更新阶段)

    • 执行时机:1.setState() 2.forceUpdate() 3.组件接收到新的props

    • 执行顺序:

      graph LR
      A(render)-->B(componentDidUpdate)
      
      钩子函数触发时机作用
      render每次组件渲染都会触发渲染UI(注意:不能调用setState())
      componentDidUpdate组件更新(完成DOM渲染)后1. 发送网络请求
      2. DOM操作
      注意:如果要setState()必须要放在一个if条件中
  3. 卸载时(卸载阶段)

    • 执行时机:组件从页面消失

      钩子函数触发时机作用
      componentWillUnmount组件卸载(从页面消失)执行清理工作(比如:清理定时器)

render props和高阶组件

1.React组件复用概述

  • 当有两个组件存在相似/相同功能时,考虑复用该功能(封装)
  • 两种方式:1. render props模式 2.高阶组件(HOC)
  • 注意:这两种模式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式

2.render props模式

/*
1. 实现时,添加一个值为函数的prop,通过函数参数来获取
*/
Mouse.propTypes = {
    children: PropTypes.func.isRequired
}

class Mouse extends React.Component{
    state = {
        x: 0,
        y: 0
    }

	handleMouseMove = e => {
        this.setState({
            x: e.clientX,
            y: e.clientY
        })
    }
    
    componentDidMount(){
        window.addEventListener('mousemove', this.handleMouseMove)
    }
	
	componentWillUnmount(){
        window.removeEventListener('mousemove', this.handleMouseMove)
    }

	render(){
        return this.props.children(this.state)
    }
}

3.高阶组件

  • 概述:实现状态逻辑复用

  • 采用包装(装饰)模式

  • 高阶组件(HOC,Higher-Order Conponent)是一个函数,接收要包装的组件,返回增强后的组件

  • 高阶组件内部创建一个类组件,在这个类组件中提供复用的逻辑状态代码,通过prop将复用的状态传递给被包装组件WrappedComponent

    function withMouse(WrappedComponent){
        Class Mouse extends React.Component{
            state ={
                x: 0,
                y: 0
            }
            
         	handleMouseMove = e => {
                this.setState({
                    x: e.clientX,
                    y: e.clientY
                })
            }
        
            componentDidMount(){
                window.addEventListener('mousemove', this.handleMouseMove)
            }
            
            componentWillUnmount(){
            	window.removeEventListener('mousemove', this.handleMouseMove)
        	}
            
            return <WrappedComponent{...this.state} />
        }
        return Mouse
    }
    
  • 设置displayName

    使用高阶组件存在问题:得到两个组件名称相同

    原因:默认情况下,React使用组件名称作为displayName

    为 高阶组件 设置 displayName,用于区分组件的不同实现

    Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
    
    function getDisplayName(WrappedComponent){
        return WrappedComponent.displayName || WrappedComponent.name || 'Component'
    }
    
  • 传递props

    {...this.props}