zoukankan      html  css  js  c++  java
  • react系列(二)高阶组件-HOC

    高阶组件

    简单来说,高阶组件可以看做一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。

    我在之前的博客《闭包和类》中提到一个观点,面向对象的好处就在于,易于理解,方便维护和复用。
    其实高阶组件,也是为了更好地复用之前的组件。它可以理解为,基础组件通过包裹处理,生成一个适应某些场景的组件。
    它可能存在于以下几种场景:

    定制props

    一个简单例子:

    function withMoreThings(WrappedComponent) {  
      return class extends React.Component {
        render() {     
          const moreThings = {
              more: 'things',
          };
          return <WrappedComponent {...this.props} ...moreThings/>    
        }  
      } 
    }
    

    这是HOC(High Order Component)最常用的一种方式,用来传递一些定制化的参数给内部组件。

    提取公共方法、属性

    在to B的项目中,表单是一个大头,所有流程都绕不开表单。也就会说到受控组件和非受控组件。

    受控组件

    由于HTML表单元素会保留一些内部状态,比如input框,它会有自己内部的状态来保存用户的输入值。

    <input type="text" name="name" />
    

    此时,为了能够处理将React的state和表单元素的内部状态统一起来,React提供了一种称为“受控组件”的技术。

    class NameInput extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ''};
    
        this.handleChange = this.handleChange.bind(this);
      }
    
      handleChange(event) {
        console.log(this);
        this.setState({value: event.target.value});
      }
    
      render() {
        return (
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        );
      }
    }
    

    通过内部的state和绑定change事件,就可以将input内部的处理机制转移到React的默认处理机制上,收到React的控制。
    但是,还是有一些元素,不能使用这种方法,比如

    <input type="file"> 
    

    这个元素是只读的,用户选择完毕后,可以获取到对应的文件。不能通过React内部的state来模拟。
    这就引出了——

    非受控组件

    非受控组件从DOM中获取表单值,而不是通过React的state来处理。由于它不经过React的一些逻辑,所以不能对它的状态做监控。这里有一篇文章Controlled and uncontrolled form inputs in React don't have to be complicated介绍了何时可以使用非受控组件。
    下面是一个非受控组件的例子:

    import React, { Component } from "react";
    export default class NameInput extends Component {
      constructor(props) {
        super(props);
      }
    
      handleChange(event) {
        console.log(this);
        this.setState({ value: event.target.value });
      }
    
      render() {
        return (
          <input
            type="text"
            defaultValue="test"
            ref={input => (this.input = input)}
          />
        );
      }
    }
    
    <input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,<input type="text"><select> 和 <textarea> 支持 defaultValue,可以帮助设置表单默认值。  
    

    非受控组件通过ref来获取DOM元素,然后根据当前DOM去更新UI。
    有关Ref的使用,参考这个文档Refs & DOM
    我个人建议,如果对于一些数据交互较少,展示和处理基本在组件内部完成,不会涉及到很多组件间数据交换的情景,可以使用非受控组件,更快,更直观。其他情况仍然建议使用受控组件,方便数据流的传导。

    接着说回高阶组件。在使用表单时,很多情境下的输入,我们都希望统一由state,或者redux来保存,而不是被dom节点存储。
    上面讲到了受控组件的使用,关键点有三:
    1.对应的onChange方法
    2.对应的存储点,state或者redux
    3.绑定到对应组件
    参考上面的描述,来实现一个高阶组件的生成函数。
    这里是一个例子:https://codesandbox.io/s/7p85l213q
    这样就可以很方便的生成受控组件。
    在一些场景下,我们也可以用其他组件包装WrappedComponent。比如,添加一些小图标,用父组件可能不够灵活,用HOC则可以很轻松地生成一个可配置的组件,灵活许多。
    React Higher Order Components in depth还提到一种生成HOC的方法,类继承,改写更彻底。详细内容可以参考这篇文章。也可以查看知乎的这篇翻译深入理解 React 高阶组件

    以上,感谢阅读。

  • 相关阅读:
    从 0 配置 webpack(一)
    Redux
    React Hooks 全解(二)
    日本人要把核污水排进大海,我突然想到几个问题
    突然发现,我的代码还花花绿绿的,挺好看的
    Ghidra ,改道吧,我也准备改道这玩意了
    语音控制?这,看起来很眼熟。
    winafl 工具的编译
    关于 TX 的 WeGame 的一点疑问
    新年的第一个随笔,随便写写吧
  • 原文地址:https://www.cnblogs.com/liuyongjia/p/9693377.html
Copyright © 2011-2022 走看看