react组件和react组件逻辑复用
react是一个视图层组件方案,最核心的功能就是绑定视图与数据和逻辑,实现响应式的渲染。react的组件最核心的就是渲染出的Vdom,也就是jsx的部分。
渲染jsx的这部分逻辑封装在一个函数内就可以了,这就是函数组件,组件的最基本形态。渲染结果只与参数有关,参数相同,每次渲染结果都相同。但有的情况下,每次渲染是不相同的,需要一个上下文来保存状态,所以会用class来封装这部分逻辑,渲染的那部分核心逻辑移到了render函数中,这就是 class 组件,组件的第二种形态。类组件除了能够保存状态,使得每次渲染结果与状态有关之外,还可以在一些组件的执行阶段加入一些处理逻辑,也就是生命周期函数。
组件之间有复用的需求,有一些可复用的逻辑需要从组件中抽取出来,变成可复用的形态,函数的逻辑复用套一层函数就好了,也就是高阶组件(HOC),类组件的复用可以传入一个参数作为渲染内容,其余部分为可复用部分,这就是render props。 这两种方案就是16.8版本之前的react所支持的组件间逻辑复用方案了。
逻辑复用方案hoc和render props的问题
但render props会多生成一层组件,HOC会改变组件名,这样在调试时会发现组件树特别不直观。而且类组件的方案中处理同一个事情的逻辑可能会散乱在多个生命周期函数中,使得组件变得越来越臃肿。种种原因,使得类组件、函数组件这两种组件形态,和HOC还有render props这两种扩展方式继续进行变革,来解决越来越严重的组件维护和逻辑复用问题。
hooks 的设计思路
渲染出Vdom也就是jsx的部分,是一个组件最核心的功能,使用类组件只是因为有一些状态需要上下文来管理,于是按照这个思路,react在16.8中加入了hooks,可以在函数组件中添加一些有自己独立上下文管理的状态(useState),不再依赖于类组件,同时一些逻辑也可以放到hooks中来复用(useEffects)。
注意,hooks之间的状态是各自独立维护的,这和mixins不同,mixins只是会把逻辑混到一个上下文中,使得之间会相互影响。而每个hooks之间都是独立的上下文,不会有mixins方案的问题。
这样之后组件形态就在函数组件(无状态),类组件之外多了函数组件(hooks管理状态)的第三种组件形态,扩展方式也在HOC、render props之外加入了hooks的组合的方案(custom hooks)。这样就完美的解决了组件树不直观、类组件难维护、逻辑不易复用这几个问题。
hooks的优缺点
hooks相当于补充了一个render前后的生命周期,很多逻辑可以移到这里面来,能够优雅的实现之前要在多个生命周期中才能完成的功能。具体的一些例子可以看(官方文档
)。
当然hooks也不是完美的,他也有自己的问题,比如hooks是每次渲染都执行的,所以性能是个问题,react的useEffects hooks支持第二个参数,可以传入依赖的状态变量,只有在变量改变时才会执行,也可以传入一个空数组,这样就只执行一次。
总结
视图层组件最核心的就是渲染出vdom也就是jsx的部分,函数组件是基本形态,有状态时可以使用类组件形态,组件间逻辑复用可以使用函数组件的HOC和类组件render props来实现,但这种状态下,存在组件树不直观、类组件难维护、组件的有状态逻辑难复用的问题,所以react 16.8加入了hooks的方案。每个hooks独立的上下文来维护状态,可以添加到函数组件中,这样函数组件就可以完成一些有状态的逻辑。逻辑复用方案也在HOC和render props之外加入了 custom hooks的方式。但hooks也不是完美的,他也有性能问题,因为每次render 都会调用,所以需要指定依赖的状态变量来优化性能。
hooks拯救react于一些越来越突出的问题之中,算是react的一个转折点吧。