react系列(二)高阶组件-HOC

高阶组件

简单来讲,高阶组件能够看作一个函数,且该函数接受一个组件做为参数,并返回一个新的组件。javascript

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

定制props

一个简单例子:java

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

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

提取公共方法、属性

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

受控组件

因为HTML表单元素会保留一些内部状态,好比input框,它会有本身内部的状态来保存用户的输入值。闭包

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

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

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的控制。
可是,仍是有一些元素,不能使用这种方法,好比dom

<input type="file">

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

非受控组件

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

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 高阶组件

以上,感谢阅读。

相关文章
相关标签/搜索