当前位置:网站首页 > React Native移动开发 > 正文

react 进阶(react 技巧)



一 前言

高阶组件(),对于很多开发者来说并不陌生,它是灵活使用组件的一种技巧,高阶组件本身不是组件,它是一个参数为组件,返回值也是一个组件的函数。高阶作用用于强化组件,复用逻辑,提升渲染性能等作用。高阶组件也并不是很难理解,其实接触过后还是蛮简单的,接下来我将按照,高阶组件理解?,高阶组件具体怎么使用?应用场景, 高阶组件实践(源码级别) 为突破口,带大家详细了解一下高阶组件。本文篇幅比较长,建议收藏观看

我们带着问题去开始今天的讨论:

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

原型图

老版本的

在初期提供一种组合方法。通过,加入属性,具体用法和 中相似。具体实现如下。

这种只能存在中,后来连同这种模式被废弃了。会带来一些负面的影响。

衍生方式

的废弃,不代表模式退出舞台,在有状态组件,我们可以通过原型链继承来实现。

原型图

在组件盛行之后,我们可以通过继承的方式进一步的强化我们的组件。这种模式的好处在于,可以封装基础功能组件,然后根据需要去我们的基础组件,按需强化组件,但是值得注意的是,必须要对基础组件有足够的掌握,否则会造成一些列意想不到的情况发生。

原型图

是我们本章主要的讲的内容,具体用法,我们接下来会慢慢道来,我们先简单尝试一个。

原型图

的诞生,一大部分原因是解决无状态组件没有和逻辑难以复用问题。可以将一段逻辑封装起来,做到开箱即用,我这里就不多讲了,接下来会出原理的文章,完成三部曲。感兴趣的同学可以看笔者的另外二篇文章,里面详细介绍了复用代码逻辑的原则和方案。

传送门:

玩转react-hooks,自定义hooks设计模式及其实战

react-hooks如何使用?

组件是把渲染成,而高阶组件是将组件转换成另外一个组件,我们更应该注意的是,经过包装后的组件,获得了那些强化,节省多少逻辑,或是解决了原有组件的那些缺陷,这就是高阶组件的意义。我们先来思考一下高阶组件究竟解决了什么问题🤔🤔🤔?

① 复用逻辑:高阶组件更像是一个加工组件的工厂,批量对原有组件进行加工,包装处理。我们可以根据业务需求定制化专属的,这样可以解决复用逻辑。

② 强化props:这个是最常用的用法之一,高阶组件返回的组件,可以劫持上一层传过来的,然后混入新的,来增强组件的功能。代表作中的。

③ 赋能组件:有一项独特的特性,就是可以给被包裹的业务组件,提供一些拓展功能,比如说额外的生命周期,额外的事件,但是这种,可能需要和业务组件紧密结合。典型案例中的 就是通过方式,给业务组件增加了额外的生命周期。

④ 控制渲染:劫持渲染是一个特性,在包装组件中,可以对原来的组件,进行,,等功能,后面会详细讲解,典型代表做中和 中  组件懒加载。

我会针对高阶组件的初衷展开,详细介绍其原理已经用法。跟上我的思路,我们先来看一下,高阶组件如何在我们的业务组件中使用的。

使用指南是非常简单的,只需要将我们的组件进行包裹就可以了。

对于声明的有状态组件,我们可以用装饰器模式,对类组件进行包装:

我们要注意一下包装顺序,越靠近组件的,就是越内层的,离组件也就越近。

对于无状态组件(函数声明)我们可以这么写:

对于不需要传递参数的,我们编写模型我们只需要嵌套一层就可以,比如,

对于需要参数的,我们需要一层代理,如下:

我们看出两种模型很简单,对于代理函数,可能有一层,可能有很多层,不过不要怕,无论多少层本质上都是一样的,我们只需要一层一层剥离开,分析结构,整个结构和脉络就会清晰可见。吃透也就易如反掌。

常用的高阶组件有两种方式正向的属性代理和反向的组件继承,两者之前有一些共性和区别。接下具体介绍两者区别,在第三部分会详细介绍具体实现。

所谓正向属性代理,就是用组件包裹一层代理组件,在代理组件上,我们可以做一些,对源组件的代理操作。在 上,先代理组件,然后才是我们的业务组件。我们可以理解为父子组件关系,父组件对子组件进行一系列强化操作。

优点

缺点

例子:

打印结果

反向继承和属性代理有一定的区别,在于包装后的组件继承了业务组件本身,所以我们我无须在去实例化我们的业务组件。当前高阶组件就是继承后,加强型的业务组件。这种方式类似于组件的强化,所以你必要要知道当前

优点

打印结果

缺点

接下来我们来看看,如何编写一个高阶组件,你可以参考如下的情景,去编写属于自己的。

这个是高阶组件最常用的功能,承接上层的,在混入自己的,来强化组件。

有状态组件(属性代理)

有状态组件(属性代理)

同样也适用与无状态组件。

效果

高阶组件可以将的的配合起来,控制业务组件的更新。这种用法在中高阶组件中用到过,用于处理来自中更改,带来的订阅更新作用。

我们将上述代码进行改造。

效果

控制渲染是高阶组件的一个很重要的特性,上边说到的两种高阶组件,都能完成对组件渲染的控制。具体实现还是有区别的,我们一起来探索一下。

① 基础 :动态渲染

对于属性代理的高阶组件,虽然不能在内部操控渲染状态,但是可以在外层控制当前组件是否渲染,这种情况应用于,权限隔离,懒加载 ,延时加载等场景。

实现一个动态挂载组件的HOC

效果:

② 进阶 :分片渲染

是不是感觉不是很过瘾,为了让大家加强对条件渲染的理解,我再做一个分片渲染+懒加载功能。为了让大家明白,我也是绞尽脑汁啊😂😂😂。

进阶:实现一个懒加载功能的HOC,可以实现组件的分片渲染,用于分片渲染页面,不至于一次渲染大量组件造成白屏效果

效果

大致流程,初始化的时候,中将渲染真正组件的渲染函数,放入队列中,然后初始化渲染一次,接下来,每一个项目组件,完成  状态后,会从队列中取出下一个渲染函数,渲染下一个组件, 一直到所有的渲染任务全部执行完毕,渲染队列清空,有效的进行分片的渲染,这种方式对海量数据展示,很奏效。

用实现了条件渲染-分片渲染的功能,实际条件渲染理解起来很容易,就是通过变量,控制是否挂载组件,从而满足项目本身需求,条件渲染可以演变成很多模式,我这里介绍了条件渲染的二种方式,希望大家能够理解精髓所在。

③ 进阶:异步组件(懒加载)

不知道大家有没有用过,里面的就是应用模式实现的组件异步加载,我这里简化了一下,提炼核心代码,如下:

使用

还可以配合其他,做一下衍生的功能。如上配合实现异步加载功能。用起来非常灵活,

④ 反向继承 :渲染劫持

HOC反向继承模式,可以实现颗粒化的渲染劫持,也就是可以控制基类组件的函数,还可以篡改props,或者是,我们接下来看看,这种状态下,怎么使用高阶组件。

⑤ 反向继承:修改渲染树

修改渲染状态(劫持render替换子节点)

效果

我们用劫持渲染的方式,来操纵后的元素,然后配合  ,  ,  等 ,可以灵活操纵,真正的渲染,可以说是偷天换日,不亦乐乎。

除了可以进行条件渲染,渲染劫持功能外,还可以进行节流渲染,也就是可以优化性能,具体怎么做,请跟上我的节奏往下看。

① 基础: 节流原理

可以配合的等配合使用,可以实现对业务组件的渲染控制,减少渲染次数,从而达到优化性能的效果。如下案例,我们期望当且仅当改变的时候,渲染组件,但是不影响接收的。我们应该这样写我们的。

效果:

如图所示,当我们只有点击 时候,才重新渲染子组件,点击其他按钮,只是负责传递了,达到了期望的效果。

② 进阶:定制化渲染流

思考:🤔上述的案例只是介绍了原理,在实际项目中,是量化生产不了的,原因是,我们需要针对不同变化,写不同的组件,这样根本起不了真正的用途,也就是产生的初衷。所以我们需要对上述进行改造升级,是组件可以根据定制化方向,去渲染组件。也就是生成的时候,已经按照某种契约去执行渲染。

效果

完美实现了效果。这用高阶组件模式,可以灵活控制组件层面上的,数据流和更新流,优秀的高阶组件有  中 , , 中的,感兴趣的同学,可以抽时间研究一下。

高阶组件除了上述两种功能之外,还可以赋能组件,比如加一些额外,劫持事件,监控日志等等。

① 属性代理实现

效果

② 反向继承实现

反向继承,因为在继承原有组件的基础上,可以对原有组件的生命周期或事件进行劫持,甚至是替换。

还可以对原有组件进行监控。比如对一些,,等一系列操作。

① 组件内的事件监听

接下来,我们做一个,只对组件内的点击事件做一个监听效果。

效果

对于属性代理我们虽然不能直接获取组件内的状态,但是我们可以通过获取组件实例,获取到组件实例,就可以获取组件的一些状态,或是手动触发一些事件,进一步强化组件,但是注意的是:声明的有状态组件才有实例,声明的无状态组件不存在实例。

① 属性代理-添加额外生命周期

我们可以针对某一种情况, 给组件增加额外的生命周期,我做了一个简单的,监听改变,如果改变,就自动触发组件的监听函数。具体写法如下

这种写法有点不尽人意,大家不要着急,在第四部分,源码实战中,我会介绍一种更好的场景。方便大家理解对原有组件的赋能。

上面我分别按照主要功能,强化props , 控制渲染 ,赋能组件 三个方向对编写做了一个详细介绍,和应用场景的介绍,目的让大家在理解高阶组件的时候,更明白什么时候会用到?,怎么样去写?` 里面涵盖的知识点我总一个总结。

对于属性代理HOC,我们可以:

对于反向代理的HOC,我们可以:

每个应用场景,我都举了例子🌰🌰,大家可以结合例子深入了解一下其原理和用途。

的应用场景有很多,也有很多好的开源项目,供我们学习和参考,接下来我真对三个方向上的功能用途,分别从源码角度解析的用途。

用过的同学,都明白其用途,用途就是,对于没有被包裹的组件,给添加对象等和路由相关的状态,方便我们在任意组件中,都能够获取路由状态,进行路由跳转,这个目的很清楚,就是强化,把相关的状态都混入到中,我们看看具体怎么实现的。

的流程实际很简单,就是先从分离出和,然后从存放整个对象上下文取出对象,然后混入到原始组件的中,最后用继承静态属性。至于我们稍后会讲到。

由于源码比较长和难以理解,所以我们提取精髓,精简精简再精简, 总结的核心功能如下,的作用也有,但是更重要的是接受,来控制更新组件。下面这个代码中,为了方便大家理解,我都给简化了。希望大家能够理解如何派发和控制更新流的。

涉及到的功能点还真不少呢,首先第一层接受订阅函数,第二层接收原始组件,然后用处理,用 处理静态属性的继承,在包装组件内部,合并,缓存原始组件,只有合并后的发生变化,才更新组件,然后在内部通过订阅更新。这里省略了概念,真正的中有一个专门负责订阅消息。

之前笔者写了一个缓存页面的开源库,可以实现中  + 功能,最初的版本没有缓存周期的,但是后来热心读者,期望在被缓存的路由组件中加入缓存周期,类似这种的,后来经过我的分析打算用来实现此功能。

于是乎加入了全新的页面组件生命周期  和 ,  作为缓存路由组件激活时候用,初始化的时候会默认执行一次 ,  作为路由组件缓存完成后调用。但是生命周期需要用一个  组件 包裹。

使用

原理

的原理很简单,就是通过或获取  组件的实例,在  初始化时候进行生命周期的绑定, 在  销毁阶段,对生命周期进行解绑, 然后交给统一调度,通过调用实例下面的生命周期函数,来实现缓存生命周期功能的。

这样做会产生一些不良后果。比如如果你再用另一个同样会修改  的  增强它,那么前面的  就会失效!同时,这个  也无法应用于没有生命周期的函数组件。

在用属性代理的方式编写的时候,要注意的是就是,静态属性丢失的问题,前面提到了,如果不做处理,静态方法就会全部丢失。

我们可以手动将原始组件的静态方法到 组件上来,但前提是必须准确知道应该拷贝哪些方法。

这样每个静态方法都绑定会很累,尤其对于开源的,对原生组件的静态方法是未知的,我们可以使用  自动拷贝所有的静态方法:

高阶组件的约定是将所有  传递给被包装组件,但这对于  并不适用。那是因为  实际上并不是一个  - 就像  一样,它是由  专门处理的。如果将  添加到  的返回组件中,则  引用指向容器组件,而不是被包装组件。我们可以通过来解决这个问题。

打印结果:

如上就解决了,跨层级捕获的问题。

🙅错误写法:

如果这么写,会造成一个极大的问题,因为每一次都会返回一个新的,会判定两次不是同一个组件,那么每次 组件 触发,,会重新挂载,状态会全都丢失。如果想要动态绑定,请参考如下方式。

🙆正确写法:

本文从高阶组件功能为切入点,介绍二种不同的高阶组件如何编写,应用场景,以及实践。涵盖了大部分耳熟能详的开源高阶组件的应用场景,如果你觉得这篇文章对你有启发,最好还是按照文章中的,跟着敲一遍,加深印象,知道什么场景用高阶组件,怎么用高阶组件。

,希望大家能把高阶组件起来,用起来。

喜欢这篇文章?欢迎打赏~~

到此这篇react 进阶(react 技巧)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • react经验(react项目经验)2025-05-24 14:00:05
  • 域名whois查询(域名whois查询 – 站长工具)2025-05-24 14:00:05
  • react入门视频教程(react 视频教程)2025-05-24 14:00:05
  • react获取地址栏参数(react 获取cookie)2025-05-24 14:00:05
  • cesium在二维地图中拖拽移动实体2025-05-24 14:00:05
  • react 组件(react组件懒加载)2025-05-24 14:00:05
  • reactui组件(react dialog组件)2025-05-24 14:00:05
  • reactui组件(react ui组件)2025-05-24 14:00:05
  • react 进阶之路(react进阶之路)2025-05-24 14:00:05
  • react 常用组件库(react组件三大属性)2025-05-24 14:00:05
  • 全屏图片