• react高阶组件


    <!-- 1. React组件复用概述 -->
    思考:如果两个组件中的部分功能相似或相同,该如何处理?
     处理方式:复用相似的功能(联想函数封装)
     复用什么?1. state 2. 操作state的方法 (组件状态逻辑 )
     两种方式:1. render props模式 2. 高阶组件(HOC)
     注意:这两种方式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)
    
    <!-- 2.实现思路 -->
    在使用组件时,添加一个值为函数的prop,通过 函数参数 来获取(需要组件内部实现)
    使用该函数的返回值作为要渲染的UI内容(需要组件内部实现)
    
    <!-- 3.render props 模式 -->
    使用步骤
    1. 创建Mouse组件,在组件中提供复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
    2. 将要复用的状态作为 props.render(state) 方法的参数,暴露到组件外部
    3. 使用 props.render() 的返回值作为要渲染的内容
    
        import React from 'react'
        import ReactDOM from 'react-dom'
        /*  render props 模式*/
        // 导入图片资源
        import img from './images/cat.png'
        // 作用:鼠标位置复用
        class Mouse extends React.Component {    //Mouse组件负责:封装复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
          // 鼠标位置state                       //状态:鼠标坐标(x, y)
          state = {      
            x: 0,   y: 0
          }
    
          // 鼠标移动事件的事件处理程序    操作状态的方法:鼠标移动事件
          handleMouseMove = e => {
            this.setState({
              x: e.clientX,
              y: e.clientY
            })
          }
          // 监听鼠标移动事件
          componentDidMount() {
            window.addEventListener('mousemove', this.handleMouseMove)
          }
          render() {     //复用方法        传入的render prop负责:使用复用的状态来渲染UI结构
            return this.props.render(this.state)  //子组件接收数据,并传参调用方法
          }
        }
    
        class App extends React.Component {
          render() {
            return (
              <div>
                <h1>render props 模式</h1>
                <Mouse
                  render={mouse => {     //父组件属性绑定方法,并return ui结构
                    return (
                      <p>
                        鼠标位置:{mouse.x} {mouse.y}
                      </p>
                    )
                  }}
                />
    
                {/* 猫捉老鼠 */}
                <Mouse
                  render={mouse => {
                    return (
                      <img
                        src={img}
                        alt="猫"
                        style={{
                          position: 'absolute',
                          top: mouse.y - 64,
                          left: mouse.x - 64
                        }}
                      />
                    )
                  }}
                />
              </div>
            )
          }
        }
        ReactDOM.render(<App />, document.getElementById('root'))
    
    <!-- 4.children代替render属性 -->
    注意:并不是该模式叫 render props 就必须使用名为render的prop,实际上可以使用任意名称的prop
     把prop是一个函数并且告诉组件要渲染什么内容的技术叫做:render props模式
     推荐:使用 children 代替 render 属性
    
    代码优化:
    1. 推荐:给 render props 模式添加 props校验
    2. 应该在组件卸载时解除 mousemove 事件绑定
    
        import React from 'react'
        import ReactDOM from 'react-dom'
        import PropTypes from 'prop-types'
    
        // 作用:鼠标位置复用
        class Mouse extends React.Component {
          state = {          // 鼠标位置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)
          }
        }
        // 添加props校验
        Mouse.propTypes = {
          children: PropTypes.func.isRequired
        }
    
        class App extends React.Component {
          render() {
            return (
              <div>
                <h1>render props 模式</h1>
                <Mouse>                   //组件children属性
                  {mouse => {
                    return (
                      <p>
                        鼠标位置:{mouse.x} {mouse.y}
                      </p>
                    )
                  }}
                </Mouse>
              </div>
            )
          }
        }
        ReactDOM.render(<App />, document.getElementById('root'))
    
    <!-- 5.高阶组件概述 -->
    目的:实现状态逻辑复用
     采用 包装(装饰)模式 ,比如说:手机壳
     手机:获取保护功能
     手机壳 :提供保护功能
     高阶组件就相当于手机壳,通过包装组件,增强组件功能
    
    思路分析:
    高阶组件(HOC,Higher-Order Component)是一个函数,接收要包装的组件,返回增强后的组件
     高阶组件内部创建一个类组件,在这个类组件中提供复用的状态逻辑代码,通过prop将复用的状态传递给
    被包装组件 WrappedComponent
        const EnhancedComponent = withHOC(WrappedComponent)
        // 高阶组件内部创建的类组件:
        class Mouse extends React.Component {
        render() {
        return <WrappedComponent {...this.state} />
        }
        }
    
    <!-- 6.高阶组件使用步骤 -->
    1. 创建一个函数,名称约定以 with 开头
    2. 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
    3. 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
    4. 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
    5. 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
    
    设置displayName
     使用高阶组件存在的问题:得到的两个组件名称相同
     原因:默认情况下,React使用组件名称作为 displayName
     解决方式:为 高阶组件 设置 displayName 便于调试时区分不同的组件
     displayName的作用:用于设置调试信息(React Developer Tools信息)
    
    传递props
     问题:props丢失
     原因:高阶组件没有往下传递props
     解决方式:渲染 WrappedComponent 时,将 state 和 this.props 一起传递给组件
    
        import React from 'react'
        import ReactDOM from 'react-dom'
        /* 高阶组件*/
        // 创建高阶组件
        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)
            }
    
            render() {
              console.log('Mouse:', this.props)
              return <WrappedComponent {...this.state} {...this.props} />       //传递props
            }
          }
    
          // 设置displayName
          Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
          return Mouse
        }
        
        function getDisplayName(WrappedComponent) {
          return WrappedComponent.displayName || WrappedComponent.name || 'Component'
        }
    
        // 用来测试高阶组件
        const Position = props => {
          console.log('Position:', props)
          return (
            <p>
              鼠标当前位置:(x: {props.x}, y: {props.y})
            </p>
          )
        }
        // 获取增强后的组件:
        const MousePosition = withMouse(Position)
    
        class App extends React.Component {
          render() {
            return (
              <div>
                <h1>高阶组件</h1>
                <MousePosition a="1" />
              </div>
            )
          }
        }
        ReactDOM.render(<App />, document.getElementById('root'))
    
  • 相关阅读:
    转:git上传本地项目到github
    转:git常用操作
    idea常用快捷键
    转:spring中InitailizingBean接口的简单理解
    resulting in duplicate entry '1' for key 'primary'
    Uncaught SyntaxError: Unexpected identifier
    This application has no explicit mapping for /error, so you are seeing this as a fallback.
    启动web项目报错:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.
    解决 "Could not autowire. No beans of 'SationMapper' type found" 的问题
    javascript 判断系统设备
  • 原文地址:https://www.cnblogs.com/xm0328/p/14013660.html
Copyright © 2020-2023  润新知