关于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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理