背景部分是我对高阶组件的理解,确保在继续具体问题前,我们的理解是一致的。
背景:
React中高阶组件是一个普通的函数。之所说它是“普通”的函数,是想和组件类区分开,因为JS中的类本质上也是函数。所以高阶组件虽然叫组件,但它并不是普通意义的 React 组件,而是一个函数。
这个函数接收一个React 组件类(姑且称为“被包装组件”)或其他可选参数,并返回一个新的组件类(姑且称为“增强型组件”)。所以你可以认为高阶组件是一个组件工厂函数。返回的组件类在 render 时往往使用“被包装组件”进行渲染。
其实,高阶组件的函数体的实现大部分都是“增强型组件”的实现,在实现中利用传递给高阶组件的参数定制化“增强型组件”的实现。
“增强型组件”是“被包装组件”的容器组件。所以 React 文档上说
You can think of HOCs as parameterized container component
definitions.(你可以把 HOC 看作是参数化的容器组件的定义)
具体问题:
那么问题来了,既然 hoc 可看做是参数化的容器组件的定义,那么 hoc 的独特意义何在呢?如果需要对一个 React 组件进行功能增强,我给它在外面套一层容器组件不就行了吗?同时容器组件也可以通过接收props 来进行实现过程的定制化,props中也可包含组件类,即“被包装组件”。高阶组件对容器组件进行定制化实现只不过是通过函数的参数,这和容器组件本身使用 props 来定制化没有本质区别。
拿 React 文档中的例子来说,文档中将 withSubscription 实现为一个高阶组件。那么我觉得就这个例子来说,withSubscription 实现为一个普通的 React 组件效果也是完全一样的。只要把 withSubscription 的函数参数变为 WithSubscription 这个普通 React 组件的 props 即可。WithSubscription 的实现也就直接是“被包装组件”的容器组件的实现了,而无需像 withSubscription 那样返回一个容器组件类。
文档上举的例子确实说明了高阶组件应用的情境,但就这个例子而言,似乎不是非高阶组件不可。那么,高阶组件这种设计模式的独特性在哪里,意义是什么?
比如说你要给每个组件(Table、Slider等等)外面都加个Loading
如果说照着题主的想法,可能是给Table或者Slider外面套一层方法,最后返回个新组件就得了
但这样Table或者Slider本身就写死了而不是一个灵活的参数,如果我下次有个Table1呢,又得写一遍
这还不算,万一我这是个状态深沉的Loading呢...
具体的情况可以去看看antd的Form,如果不抽象一下真的欲仙欲死
这玩意就是为了少写重复的代码的,独特性倒还真没觉得
题主也说了这是个设计模式,没碰上实际场景的时候它的确没用,并不是什么非它不用的东西
碰见了,知道有这个东西了,那问题就会简单很多了
以上是我云出来的,并没有实际操作过,只是知道有这么个东西
我实际操作过的所谓的“高阶组件”反而是用在了以下场景:
原先的组件不成熟,但又急着上线,后来有时间了要重写
改成成熟版本以后和原先版本用法差异很大,但又要兼容之前项目的用法
于是干脆组件本体改个名字,然后外面包一层跟原先一样的名字的皮,就这么将就用着先的这么一种“被动高阶”
仔细查了下,我发现对高阶组件的理解还是片面了