• HOC
  • RenderProps
  • Hooks

一个可视化界面

  • Container
    • 负责发送数据
  • Panel
    • 展示title
    • 通用功能
      • 同环比功能,环比同比的触发功能
      • debug功能,展示请求的json数据
    • 进行功能扩展
      • 在Header右侧支持功能的拓展
  • Line
    • 可视化展示界面

组件思想 逻辑UI分离

React 组件复用和组合 (一) | CaelumTian的博客 这里有讲到smart组件和dumb组件思想

SMART组件,负责应用逻辑,数据打交道。

DUMB组件,木偶组件,渲染结果只依赖于props,不应该依赖处React组件和其他DUMB组件

可复用逻辑有哪些

  • 交互逻辑
  • 业务逻辑
  • 区块逻辑

有哪些组件?

React逻辑复用的特征

逻辑复用需要什么? 数据和action(可理解为变更数据)。即数据决定页面渲染,action是响应界面操作变更。

以一个弹窗逻辑为例

  • 数据,即弹窗当前开关的状态。
  • action,即改变弹窗逻辑的toggle函数。

HOC

设计思想

hoc1(hoc2(component))

通过包裹,React的单向流动的设计,并通过props把数据和action传递到子组件。

有哪些实践的HOC

  • Redux的connect
  • Antd表单

实践,通过connect传入相应的特定配置

如何交互的

  • 通过props传入数据和action

问题

先明确概念

终组件 = hoc1(hoc2(原组件)))

  • 不确定性(隐式依赖) & 命名冲突 & 代码难理解

原组件最终使用的props不确定是来自哪个HOC(高阶组件)带来的。

Hoc和原组件都使用从终组件传入的props,可能会导致命名冲突。

代码难理解,在终组件传入属性被哪个hoc消费,哪个hoc有什么监控逻辑,包裹了哪些hoc都不知道。

解法,要尽量减少hoc需要传入的属性,在connect就进行过属性名定制。

  • 静态方法 & Ref 没法复制

因为层层包裹,Ref访问到原有组件,也无法放到到原有组价的静态方法

解法。

上面图表的实践

  1. const DruidContainerHoc =
  2. const PanelHoc =
  3. const LineChart =
  4. const ContainerPanelLine = DruidContainerHoc( PanelHoc (LineChart) ));
  5. // 所有的相关运行态配置都在一起了
  6. <ContainerPanelLine
  7. ...lineChartConfig
  8. ...PanelConfig
  9. ...ContainerConfig
  10. </>

RenderProps

思想

function as child

一些用例

https://github.com/jaredpalmer/awesome-react-render-props

分类


上面案例实现

  1. class Component{
  2. render(){
  3. return (<DruidContainer api={} params={}>
  4. {(data, loading, requestJSON)=>{
  5. return <Panel title="" loading={loading} requestJSON={requestJSON}>
  6. <LineChart
  7. xAisx
  8. yAisx
  9. data={data}
  10. // 可能还有一些操作
  11. />
  12. <Panel/>
  13. }}
  14. </DruidContainer>
  15. })
  16. }

Hooks

  1. function render(){
  2. const {data, loading, requestJSON} = useDruid(props);
  3. return <Panel >
  4. <LineChart/>
  5. </Panel>
  6. }
  7. function DruidContainer(props){
  8. useEffect()
  9. }

总结

HOC renderProps Hooks
拦截 function as child 钩子沟住动态
大概图 target = hoc1(hoc2(原组件))



在使用时只看到这个target组件

{props=>{
return
{props2=>{
return <元组件 …props …props2>
}

}}


<>
<原组件>

各个组件是展开的 | function(){
const {} = useFunc1()
const
}

各个依赖也是展开的 | | 优缺点 | 优点

- 可以不修改组件基础上,对组件极大改造。拦截和增强。


缺点

- 隐式依赖,不知道属性来自哪个hoc
- 属性会引起冲突
- 外界获取原组件困难
| 优点

- 显性依赖,


缺点

- 如果使用多,嵌套的地狱
- 只能在render时才能暴露出来,调用局限
| 优点

- 避免了组件的嵌套
- 更是UI和数据逻辑的分离
| | 案例 |
- 做拦截,如权限、跳转、埋点、异常、描述、注入
- 层级少时做依赖注入非常方便,如redux的connect
| | | | | | | |

借鉴

renderProps的一些库