乐趣区

关于javascript:React魔法堂echartsforreact源码略读

前言

在以后工业 4.0 和智能制作的产业降级浪潮当中,智慧大屏无疑是展现企业 IT 成绩的最无效形式之一。然而其背地怎么能短少 ECharts 的身影呢?对于 React 利用而言,间接应用 ECharts 并不是最高效且优雅的形式,而 echarts-for-react 则是针对 React 利用对 ECharts 进行轻量封装和加强的工具库。

echarts-for-react 的源码十分精简,本文将针对次要逻辑剖析介绍。

从与原生初始化比照开始

原生 ECharts 中咱们会通过如下代码初始化图表实例

<div id="container" style="width: 100px; height: 100px"></div>
<script>
  const chart = echarts.init(document.getElementById('container'))
</script>

那么生成的 HTML Element 构造为

<div id="container" style="width: 100px; height: 100px" _echarts_instance=".....">
  <div style="width: 100px; height: 100px;position: relative;">
    <canvas width="100" height="100"></canvas>
  </div>
</div>

其中第二层的 div 和 canvas 的宽高默认为容器 div#container 的宽高,咱们能够通过 init 入参指定两者宽度。

const chart = echarts.init(document.getElementById('container'), 
  null, 
  { 
    width: 300, // 可显式指定实例宽度,单位为像素。如果传入值为 null/undefined/'auto',则示意主动取 dom(实例容器)的宽度
    height: 300 // 可显式指定实例高度,单位为像素。如果传入值为 null/undefined/'auto',则示意主动取 dom(实例容器)的高度
  }
)

留神:若此时容器 div#container 尺寸发生变化,第二层 div 和 canvas 尺寸并不会自适应,须要咱们手工调用 chart.resize() 触发。

而通过 echarts-for-react 上述步骤将被简化为如下,并且生成雷同的 HTML Element 构造:

import ReactECharts from 'echarts-for-react'

function Demo() {
  return (
    <ReactECharts
      style={{width: 100, height: 100}} // 设置容器的宽高
      autoResize={true} // 默认为 true,主动监测容器尺寸的变动,并调用 `chart.resize()`
    />
  )
}

陷阱 - 默认值 height 为 300px

因为 ReactEChartsstyle默认内置height: 300,源码如下:

// src/core.tsx

render(): JSX.Element {const { style, className = ''} = this.props
  const newStyle = {height: 300, ...style}

  return (
    <div
      ref={(e: HTMLElement) => {this.ele = e}}
      style={newStyle}
      className={`echarts-for-react ${className}`}
    />
  )
}

因而通过 className 的形式设置容器高度时必须应用!important

<ReactECharts
  className={styles.container}
/>
// index.module.css
.container {height: 500px !important;}

获取 ECharts 实例

const ref = useRef()

useEffect(() => {const instance = ref.current.getEchartsInstance()
}, [])

<EchartsReact
  ref={ref}
/>

主逻辑源码分析

外围逻辑均在 EChartsReactCore 组件上(位于文件src/core.tsx),特点如下:

  1. 采纳 PureComponent 形式编写组件以便适配所有 React 版本;
  2. 仅对 ECharts 命令式 API 进行申明式 API 的封装,并没有将每种 EChart 图表类型封装为组件;
  3. 增加个性,监测容器尺寸的变动,并主动调用 ECharts 实例的 resize 办法实现自适应。

挂载渲染过程

  1. componentDidMount 时调用 renderNewEcharts 办法执行 ECharts 组件的生成逻辑;
  2. renderNewEcharts办法外部逻辑

    1. 通过 echarts.getInstanceByDom(容器 DOM 元素)echarts.init(容器 DOM 元素, 主题, 配置)获取已有 ECharts 实例或生成新的 ECharts 实例;
    2. 通过 ECharts 实例的 setOption 办法设置或更新图表内容;
    3. 通过 ECharts 实例的 showLoadinghideLoading管制图表渲染前是否显示加载进度条;
    4. 将通过 props onEvents配置的 ECharts 反对的事件处理器绑定到 ECharts 实例上;
    5. 触发 props onChartsReady 办法;
    6. 订阅通过 size-sensor 监测容器尺寸并主动调用 ECharts 实例的 resize 办法,实现图表尺寸的自适应。

更新渲染过程

因为 render 办法无论执行多少遍,实际上仅仅有可能影响容器自身而已,对 ECharts 实例并没有任何影响。因而理论影响 ECharts 实例的逻辑被搁置到 componentDidUpdate 那里,这做法和 react-amap 中在 useEffect 中通过 Marker 等实例内置的 set 办法更新状态的原理是统一的。

  1. 若更新的 props 蕴含 theme, optsonEvents则要销毁原来的 ECharts 实例,从新构建一个新的 ECharts 实例,并终止更新渲染过程;否则执行第 2 步。
  2. 若 props 中的 option,notMergela,lazyUpdate,showLoadingloadingOption均没有变动,则不更新 ECharts 实例;
    留神:EChartsReactCore 继承 PureComponent,若上述 props 进行 shallow equal 比拟为 true 时也不会更新 ECharts 实例;但这一步采纳 deep equal 比拟,来缩小 ECharts 实例的更新。
  3. 若 props 中的 styleclassName发生变化则会触发 ECharts 实例的 resize 办法。

卸载过程

  1. 勾销通过 size-sensor 订阅的容器尺寸变动事件;
  2. 通过 ECharts 实例的 dispose 办法登记 ECharts 实例。

我的项目依赖

  • fast-deep-equal: 遍历对象属性进行比照
  • size-sensor: DOM 元素尺寸监听器,当元素尺寸变动时会触发回调函数

后续

echarts-for-react 利用 size-sensor 实现图表尺寸自适应容器尺寸,那么 size-sensor 是怎么做到这一点呢?敬请期待一下篇《React 魔法堂:size-sensor 源码略读》。

尊重原创,转载请注明来自:https://www.cnblogs.com/fsjoh… ^_^ 肥仔 John

退出移动版