高阶组件

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

我在之前的博客《闭包和类》中提到一个观点,面向对象的好处就在于,易于理解,方便维护和复用。

其实高阶组件,也是为了更好地复用之前的组件。它可以理解为,基础组件通过包裹处理,生成一个适应某些场景的组件。

它可能存在于以下几种场景:

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

以上,感谢阅读。

react系列(二)高阶组件-HOC的更多相关文章

  1. React中的高阶组件

    高阶组件(HOC, High-Order Component)是React中用于重组组件逻辑的高级技术,是一种编程模式而不是React的api. 直观来讲,高阶组件是以某一组件作为参数返回一个新组件的 ...

  2. 高阶函数 HOF & 高阶组件 HOC

    高阶函数 HOF & 高阶组件 HOC 高阶类 js HOC 高阶函数 HOF 函数作为参数 函数作为返回值 "use strict"; /** * * @author x ...

  3. React中的高阶组件,无状态组件,PureComponent

    1. 高阶组件 React中的高阶组件是一个函数,不是一个组件. 函数的入参有一个React组件和一些参数,返回值是一个包装后的React组件.相当于将输入的React组件进行了一些增强.React的 ...

  4. React: 高阶组件(HOC)

    一.简介 如我们所知,JavaScript有高阶函数这么一个概念,高阶函数本身是一个函数,它会接收或者返回一个函数,进而对该函数进行操作.其实,在React中同样地有高阶组件这么一个东西,称为HOC, ...

  5. 高阶组件 HOC

    一. A higher-order component (HOC) is an advanced technique in React for reusing component logic. a h ...

  6. 高阶函数HOF和高阶组件HOC(Higher Order Func/Comp)

    一.什么是高阶函数(组件),作用是什么? 子类使用父类的方法可以通过继承的方式实现,那无关联组件通信(redux).父类使用子类方法(反向继承)呢 为了解决类(函数)功能交叉/功能复用等问题,通过传入 ...

  7. React进阶之高阶组件

    前言 本文代码浅显易懂,思想深入实用.此属于react进阶用法,如果你还不了解react,建议从文档开始看起. 我们都知道高阶函数是什么, 高阶组件其实是差不多的用法,只不过传入的参数变成了react ...

  8. 函数式编程与React高阶组件

    相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...

  9. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

随机推荐

  1. select获取选中项的值与文本

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  2. Java函数调用总结

    //思考:1.方法能不能写方法 2.为什么不能写 public static void main(String[] args) { public static void name(){}; } 方法中 ...

  3. Python入门-函数进阶

    昨天我们简单的了解了函数的定义,调用,以及传参,其实还有一个更重要的传参:动态传参,让我们继续昨天没有说完的,以及今天我要分享的东西. 一.动态传参 之前我们说过了传参,如果我们需要给一个函数传参,而 ...

  4. JS常见的几种数组去重方法

    总结一下JS中用到的数组去重的方法  方法一: 该方法利用对象的属性值不能相同: function arrDelLikeElement (array) { const result = []; con ...

  5. MongoDB 删除集合

    drop() 方法 MongoDB 的 db.collection.drop() 是用来从数据库中删除一个集合. 语法: drop() 命令的基本语法如下 db.COLLECTION_NAME.dro ...

  6. less @import and extend及mixin详解

    在less中,通过 @import (keyword) "filename"的方式引入其他的文件,这个keyword可以是以下6种: referrence referrence这个 ...

  7. centos7和centos6区别

    CentOS 7 vs CentOS 6的不同   (1)桌面系统[CentOS6] GNOME 2.x[CentOS7] GNOME 3.x(GNOME Shell) (2)文件系统[CentOS6 ...

  8. SSH框架里的iHiberBaseDAO类与iHiberDAOImpl写法

    一.iHiberBaseDAO类 package basic; import java.util.*; /** * 基于hibernate技术实现的BaseDAO基类 * @author ZHANGY ...

  9. Oracle 内存使用建议性能视图

    下面三个查询结果均可查询出随着内存参数设置的变化性能的变化情况,对oracle数据库内存的设置有一定的建议和指导作用. select t.SGA_SIZE,t.ESTD_DB_TIME_FACTOR ...

  10. selenium层级定位及鼠标键盘操作

    #code:utf-8 from selenium import webdriver from selenium.webdriver.common.action_chains import Actio ...