• React-render-props和高阶组件


    一、组件复用概述

      在实际开发中,如果有个功能基本一致,那么如何来进行处理:

      就是将两个功能,进行抽离封装成一个公用的组件,来进行使用,来进行复用(联想函数封装)

      在封装组件的过程中,需要封装哪些东西:1.state -- 数据 2.操作数据的方法

      React 中的解决方案(两种方式):render-props、高阶组件

    二、render props 模式

    import React from 'react'
    
    /**
     * 1、先创建组件,在组件内部声明 复用的 state 以及操作 state 的方法
     * 2、将要复用的数据作为 props.render(state) 方法的参数,暴露到组件外部
     */
    
     // 不能使用函数组件,因为函数组件没有自己的私有数据
     //  1、先创建组件,在组件内部声明 复用的 state 以及操作 state 的方法
     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)
       }
    
       render() {
         // 2、要复用的数据作为 props.render(state) 方法的参数,暴露到组件外部
        //  return this.props.render(this.state)
        return this.props.render()
       }
     }
    
     class App extends React.Component {
       render() {
         return (
           <div>
             {/* 在使用组件时,添加一个值为函数的prop,通过函数传参  */}
             <Mouse render={(Mouse) => (
               // 如何渲染任意的 UI 
               // 使用该函数的返回值作为要渲染的 UI 内容
              <div>
                <p>x:{Mouse.x}</p>
                <p>y:{Mouse.y}</p>
              </div>
             )}/>
           </div>
         )
       }
     }
    
     export default App

    使用 children 替换 render

    import React from 'react'
    import img from '../images/cat.png'
    
    // 定义一个复用组件
    class Mouse extends React.Component {
      // 1、定义数据
      state = {
        x: 0,
        y: 0
      }
    
      // 2、定义方法
      handleMouseMove = e => {
        this.setState({
          x: e.clientX,
          y: e.clientY
        })
      }
    
      componentDidMount() {
        // 监听鼠标移动
        window.addEventListener('mousemove',this.handleMouseMove)
      }
    
      render() {
        return this.props.children(this.state)
      }
    }
    
    class App extends React.Component {
      render() {
        return(
          <div>
            {/* 鼠标移动 */}
            <Mouse>
            {
              mouse => (
                <div>
                  <p>x: {mouse.x}</p>
                  <p>y: {mouse.y}</p>
                </div>
              )
            }          
            </Mouse>
            {/* 猫捉老鼠 */}
            <Mouse>
              {
                mouse => (
                  <img src={img} style={{position: 'absolute',top: mouse.y,left: mouse.x}}/>
                )
              }
            </Mouse>
          </div>
        )
      }
    }
    
    export default App

    三、高阶组件

    import React from 'react'
    import img from '../images/cat.png'
    
    /**
     * 高阶组件说白了就是包裹、嵌套
     */
    
    // 1.创建一个函数,名称以 with 开头
    // 2.指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
    // WrapperComponent 这是一个形参,代表是以后要增强的组件
    function withMouse(WrapperComponent) {
      // 3、创建类组件,并返回
      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)
        }
    
        // 4、在类组件内部,返回传入的组件,并传递复用的数据
        render() {
          return <WrapperComponent {...this.state} />
        }
      }
    
      Mouse.displayName = `with${getDisplayName(WrapperComponent)}`
    
      function getDisplayName(WrapperComponent) {
        return WrapperComponent.displayName || WrapperComponent.name || 'Component'
      }
    
      return Mouse
    }
    
    // 5、写 UI 结构,用来测试高阶组件
    const Position = props => {
      return (
        <p>
          鼠标当前位置:(x: {props.x}, y: {props.y})
        </p>
      )
    }
    
    // 猫捉老鼠
    const Cat = props => {
      return (
        <img src={img} alt="" style={{
          position: 'absolute',
          top: props.y - 64,
          left: props.x - 64
        }}/>
      )
    }
    
    // 6、调用高阶组件,传入要增强的组件,会返回一个增强的组件
    const MousePosition = withMouse(Position)
    const MouseCat = withMouse(Cat)
    
    class App extends React.Component {
      render() {
        return (
          <div>
            <MousePosition></MousePosition>
            <MouseCat></MouseCat>
          </div>
        )
      }
    }
    
    export default App

    四、高阶组件添加 displayName

      ① 使用高阶组件存在的问题:得到的两个组件名称相同
     
      ② 原因:默认情况下,React使用组件名称作为 displayName
     
      ③ 解决方式:为 高阶组件 设置 displayName 便于调试时区分不同的组件
     
      ④ displayName 作用:用于设置调试信息(React Developer Tools信息)

      ⑤ 添加方式:

    Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
    function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component' }
    import React from 'react'
    import img from '../images/cat.png'
    
    /**
     * 高阶组件说白了就是包裹、嵌套
     */
    
    // 1.创建一个函数,名称以 with 开头
    // 2.指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
    // WrapperComponent 这是一个形参,代表是以后要增强的组件
    function withMouse(WrapperComponent) {
      // 3、创建类组件,并返回
      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)
        }
    
        // 4、在类组件内部,返回传入的组件,并传递复用的数据
        render() {
          return <WrapperComponent {...this.state} />
        }
      }
    
      Mouse.displayName = `with${getDisplayName(WrapperComponent)}`
    
      function getDisplayName(WrapperComponent) {
        return WrapperComponent.displayName || WrapperComponent.name || 'Component'
      }
    
      return Mouse
    }
    
    // UI 结构,用来测试高阶组件
    const Position = props => {
      return (
        <p>
          鼠标当前位置:(x: {props.x}, y: {props.y})
        </p>
      )
    }
    
    // 猫捉老鼠
    const Cat = props => {
      return (
        <img src={img} alt="" style={{
          position: 'absolute',
          top: props.y - 64,
          left: props.x - 64
        }}/>
      )
    }
    
    // 5、调用高阶组件,传入要增强的组件,会返回一个增强的组件
    const MousePosition = withMouse(Position)
    const MouseCat = withMouse(Cat)
    
    class App extends React.Component {
      render() {
        return (
          <div>
            <MousePosition></MousePosition>
            <MouseCat></MouseCat>
          </div>
        )
      }
    }
    
    export default App
  • 相关阅读:
    hdu 4825 Xor Sum (01 Trie)
    hdu 5877 Weak Pair (Treap)
    bzoj 1861: [Zjoi2006]Book 书架 (splay)
    bzoj 1503: [NOI2004]郁闷的出纳员 (splay)
    hihocoder#1333 : 平衡树·Splay2 (区间操作)
    「BZOJ1251」序列终结者 (splay 区间操作)
    二进制运算符的相关运算
    Bzoj 1085: [SCOI2005]骑士精神 (dfs)
    Bzoj 1083: [SCOI2005]繁忙的都市 (最小生成树)
    Bzoj 1088: [SCOI2005]扫雷Mine (DP)
  • 原文地址:https://www.cnblogs.com/xiaowzi/p/12368706.html
Copyright © 2020-2023  润新知