浅谈react 高阶组件

1. 前言

1.高阶组件是 react组件总结中最难的一种,平常基本用不到,就算能用到也给规避了,所以也导致很多人不会
2.这几天结合之前的一些粗浅经验,搞了个简单的梳理,最终梳理出几个相对简单易懂的课件,不足之处,欢迎交流


2. 是什么 what

高阶组件(Higher Order Component,简称:HOC ):

1.是 React 中用于重用组件逻辑的高级技巧.
2.HOC 自身不是 React API的一部分,它是一种基于 React 的组合特性而形成的设计模式
3.高阶组件参数为组件,返回值为新组件的函数


简单理解

一个高阶组件只是一个包装了另外一个 React 组件的 组件。
这种形式通常实现为一个函数,本质上是一个类工厂(class factory


3.优点

1.实现了对原有组件的增强和优化,
2.可以对原有组件中的state, props和逻辑执行增删改操作, 一般用于代码重用和组件增强优化


4. 应用场景

  1. 需要代码重用时, react如果有多个组件都用到了同一段逻辑, 这时,就可以把共同的逻辑部分提取出来,利用高阶组件的形式将这段逻辑整合到每一个组件中, 从而减少代码的逻辑重复
  1. 需要组件增强优化时, 比如我们在项目中使用的组件有些不是自己写的, 而是从网上撸下来的,但是第三方写的组件可能比较复杂, 有时不能完全满足需求, 但第三方组件不易修改, 此时也可以用高阶组件,在不修改原始组件的前提下, 对组件添加满足实际开发需求的功能
    3.其实主要就是针对优点 的应用
    4.也可以用来替换 mixins 混入

4. 组件和 高阶组件的区别

1.组件是将 props 转换为 UI
2.高阶组件是将组件转换为另一个组件


5. 实现方式

5.1 属性代理

(Props Proxy): 通过创建新组件来包裹原始组件, 把原始组件作为新组件的子组件渲染
功能: 可实现对原始组件的 props数据更新 和 组件模板更新


5.2 反向继承

(Inheritance Inversion): 通过创建新组件继承自原始组件, 把原始组件作为父组件
功能: 可实现对原始组件的state状态数据更新 和 组件模板更新


好了已经一大堆理论了,上代码 再接着理论

6. 铺垫 引出工作/代码

6.1 代码

    localStorage.setItem("userInfo", JSON.stringify({ name: "yzs", description: "生活如此多娇" }))
        class UserView extends React.Component {
            constructor(props) {
                super(props)
                this.state = { userInfo: {} }

            }
            componentDidMount() {
                let userInfo = JSON.parse(localStorage.getItem("userInfo"))
                this.setState({ userInfo })
            }
            render() {
                let { userInfo } = this.state
                return (
                    <div>
                        <h1>{userInfo.name}</h1>
                        <p>{userInfo.description}</p>
                    </div>
                )
            }
        }

6.2 分析

1.上述 获取 userInfo的逻辑要在好多地方使用,
2.那么在使用的地方都需要重写 constructor componentDidMount ,显然这是冗余操作
3.这个时候需要代码 重用,所以可以选择高阶组件,对应上述的优点之一


7. 属性代理 用法

高阶函数的基本结构是 函数,参数是组件,返回新的组件
所以基本写法都是差不多的

7.1 基本结构

        function withUserData(WrappedComponent) {
            return class extends React.Component {
                constructor(props) {
                    super(props)
                    this.state = { userInfo: {} }

                }
                componentDidMount() {
                    let userInfo = JSON.parse(localStorage.getItem("userInfo"))
                    this.setState({ userInfo })
                }
                render() {
                    // ...this.props 传递给当前组件的属性继续向下传递
                    return <WrappedComponent userInfo={this.state.userInfo} {...this.props} />
                }
            }
        }

7.2 分析

1.函数名字可以随便起
2.参数名一般都是WrappedComponent, ed代表被包裹 ,所以整体代表 被包裹的组件,


注意

3.这里只封装了获取 userInfo数据的逻辑,render,布局可以不管
4.然后以属性的形式传递给包装的组件WrappedComponent
5.WrappedComponent 中直接通过 props属性获取需要的数据
6.其他组件也需要这段逻辑时就可以通过withUserData 高阶组件包装组件来使用


拔高

1.高阶组件的主要功能是封装并分离组件的通用逻辑,让通用逻辑在组件间更好地被复用。
2.高阶组件的这种实现方式,本质上是一个装饰者设计模式。


8. 使用高阶组件

8.1 需要使用的组件

  class UserView2 extends React.Component {
            render() {
                // 注意这里变为 props属性接收传值
                let { userInfo } = this.props
                return (
                    <div>
                        <h1>{userInfo.name}</h1>
                        <p>{userInfo.description}</p>
                    </div>
                )
            }
            // 省略其他逻辑,重点是当前知识点
        }

这个组件也需要用到获取 userInfo数据的逻辑


8.2 和高阶组件联合使用

        const UserHOC = withUserData(UserView2)

函数调用,参数是组件


8.3 显示

 let App = () => {
            return (
                <div>
                    <h1>App</h1>
                    <UserView />
                    <UserHOC />
                </div>
            )
        }
        ReactDOM.render(<App />, document.querySelector("#app"))

直接作为组件来使用


9. 高阶组件与父组件区别

这里很多道友有疑问了,这不和父组件一样嘛干啥这么麻烦呢

1.首先从逻辑的执行流程上来看,高阶组件确实和父组件比较相像,
2.但是高阶组件强调的是逻辑的抽象。高阶组件是一个函数,函数关注的是逻辑;
3.父组件是一个组件,组件主要关注的是UI/DOM。如果逻辑是与DOM直接相关的,那么这部分逻辑适合放到父组件中实现;
4.如果逻辑是与DOM不直接相关的,那么这部分逻辑适合使用高阶组件抽象,如数据校验、请求发送等。


10.后续

看来一篇文章还真不行,接着写


参考资料

react-组件总结
react 高阶组件-中文官网


初心

我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理,如有错误,道友们一起沟通交流;
如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
共勉
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容