资讯专栏INFORMATION COLUMN

动手写个React高阶组件

xiaokai / 1268人阅读

摘要:作用是给组件增减属性。如果你的高阶组件不需要带参数,这样写也是很的。那么需要建立一个引用可以对被装饰的组件做羞羞的事情了,注意在多个高阶组件装饰同一个组件的情况下,此法并不奏效。你拿到的是上一个高阶组件的函数中临时生成的组件。

是什么

简称HOC,全称 High Order Component。作用是给react组件增减props属性。

怎么用

为什么不先说怎么写?恩,因为你其实已经用过了,举个例子:

// App.js

import {connect} from "react-redux";

class App extends React.Component {
  render() {}
}

export default connect()(App);

熟悉不?redux的连接器。不过笔者有洁癖,喜欢用装饰器:

// App.js

import {connect} from "react-redux";

@connect()
export class App extends React.Component {
  render() {}
}
开始写

connect()()可以看出,connect是一个函数,返回值是个react组件。这么聪明,好佩服自己啊。

雏形
// myHoc.js
import React from "react";

export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return ;
      }
    }
    
    return Hoc;
  };
};

是的,高阶组件的雏形,就是函数里隐藏了一个react组件,而参数Wrapped是什么?就是下面被装饰的组件:

// App.js

@myHoc()
export class App extends React.Component {
  render() {}
}

恩恩,表现形式和redux的connect一模一样。
所以用了高阶组件后,export出去的不再是你自己写的App(Class),而是最后一个高阶。

增加props属性

好的啦,现在用myHoc给App组件加点料:

// myHoc.js
export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return ;
      }
    }
    
    return Hoc;
  };
};
// App.js

@myHoc()
export class App extends React.Component {
  render() {
    return 
{this.props.whoAmI}
; } }

放心,此刻浏览器里已经把我的名字 原罪 打印出来了。

多个高阶组件

是的,写完一个hoc之后,你就会有写第二个的需求,那就一起用呢:

// App.js

@myHoc()
@yourHoc()
@hisHoc()
@herHoc()
export class App extends React.Component {
  render() {
    return 
{this.props.whoAmI}
; } }

这就是笔者为啥要用装饰器的原因,简洁,看起来舒服,写起来快,我们看一下另一种写法:

class App extends React.Component {
  render() {}
}

export default myHoc()(yourHoc()(hisHoc()(herHoc()(App))));

自己体会,格式化一下吧:

class App extends React.Component {
  render() {}
}

let hoc;
hoc = herHoc()(App);
hoc = hisHoc()(hoc);
hoc = yourHoc()(hoc);
hoc = myHoc()(hoc);

export default hoc;

写得累不?来,给你条毛巾擦擦汗

带参数

对了,hoc可以接收参数,比如这样:

// App.js

@myHoc("原罪2号")
export class App extends React.Component {
  render() {
    return 
{this.props.whoAmI}
; } }

那高阶组件怎么接呢?

// myHoc.js

export const myHoc = (name) => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return ;
      }
    }
    
    return Hoc;
  };
};

我把hoc接收到的参数又返还给了App组件,那现在浏览器输出的就是:原罪2号

不带参数

现在,你可能有一个大胆的插法..哦不,想法,就是@myHoc后面可以不加括号吗?是哦,看前面几个案例,都是@myHoc()。好的,看我的:

// myHoc.js

export const myHoc = (Wrapped) => {
  class Hoc extends React.Component {
    render() {
      return ;
    }
  }
    
  return Hoc;
};
// App.js

@myHoc
export class App extends React.Component {
  render() {
    return 
{this.props.whoAmI}
; } }

细心的看官看一下myHoc.js和带参数的时候有什么区别。是的,少了一层回调。如果你的高阶组件不需要带参数,这样写也是很ok的。

操控原组件

你可能需要拿被装饰的组件的state数据或者执行它的方法。那么需要建立一个引用:

// myHoc.js

import React from "react";

export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      appRef = null;
      
      componentDidMount() {
        // 可以对被myHoc装饰的组件做羞羞的事情了,:)
        console.log(this.appRef);
      }
    
      render() {
        return  {this.appRef = app}} >;
      }
    }
    
    return Hoc;
  };
};

注意: 在多个高阶组件装饰同一个组件的情况下,此法并不奏效。你拿到的ref是上一个高阶组件的函数中临时生成的组件。而且在大多数情况下,你并不知道某个组件会被多少个高阶装饰!

总结

当项目中多处用到某个逻辑方法,但是这个逻辑不能放到util里的时候,HOC适合你。一个HOC最好只做一件事,这样维护方便

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95638.html

相关文章

  • 学习es7的Decorator(顺带写个react高阶组件)

    摘要:为了代码进一步解耦,可以考虑使用高阶组件这种模式。开源的高阶组件使用提供了一系列使用的高阶组件,可以增强组件的行为,可以利用此库学习高阶组件的写法。通过使用此库提供的高阶组件,可以方便地让列表元素可拖动。 1. Decorator基本知识 在很多框架和库中看到它的身影,尤其是React和Redux,还有mobx中,那什么是装饰器呢。 修饰器(Decorator)是一个函数,用来修改类的...

    xiyang 评论0 收藏0
  • 写一本关于 React.js 的小书

    摘要:因为工作中一直在使用,也一直以来想总结一下自己关于的一些知识经验。于是把一些想法慢慢整理书写下来,做成一本开源免费专业简单的入门级别的小书,提供给社区。本书的后续可能会做成视频版本,敬请期待。本作品采用署名禁止演绎国际许可协议进行许可 React.js 小书 本文作者:胡子大哈本文原文:React.js 小书 转载请注明出处,保留原文链接以及作者信息 在线阅读:http://huzi...

    Scorpion 评论0 收藏0
  • React入门0x018: 高阶函数组件(HOC)

    摘要:总结其实,这个和的思想有很大的渊源,不推荐继承,而是推荐组合,而就是其中的典范。比如我们写了两个个高阶组件,一个是,一个是,组件就可以随意的在和之间随意切换,而不需要改动组件原有代码。 0x000 概述 高阶函数组件...还是一个函数,和函数组件不同的是他返回了一个完整的组件...他返回了一个class!!! 0x001 直接上栗子 照常,先写个App组件,外部传入一个theme ...

    QLQ 评论0 收藏0
  • 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)

    手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中。学完这一章,你就可以开始自己的react项目了。 之前在思否看到过某个大神的redux搭建 忘记了大神的名字 这里只记得内容了 凭借记忆和当时的学习路线写下本文 隔空感谢 本人学习react-redux的时候遇到了很多坎,特别是不理解为什么这么用,这是什么东西,用来做什么。加上各种名词让人...

    sixgo 评论0 收藏0
  • 动手实现 redux

    摘要:动手实现实现这个模块直接创建的函数考虑到要暴露出去的三个函数我们用函数内部的变量来存储我们的数据时候直接返回当前的值就可以了同样用内部变量来存储订阅者订阅者则由函数添加返回取消订阅的函数。则根据返回新的同时通知订阅者执行相关逻辑。 文章地址 实例回顾 showImg(https://segmentfault.com/img/bVXtft?w=640&h=320); 假如按钮和界面不在同...

    Barrior 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<