前言

在当前工业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/fsjohnhuang/p/16792575.html _肥仔John

React魔法堂:echarts-for-react源码略读的更多相关文章

  1. JS魔法堂: Native Promise Only源码剖析

    一, 前言 深入学习Promise的朋友应该都看过<深入理解Promise五部曲>这一系列的文章, 以解除回调地狱之外的观点来剖析Promise更多的内涵,确实十分精彩. Part 1: ...

  2. React魔法堂:size-sensor源码略读

    前言 echarts-for-react在对echarts进行轻量级封装的基础上,额外提供图表尺寸自适应容器尺寸的这小而实用的功能,而这功能的背后就是本文想介绍的size-sensor了. 源码介绍 ...

  3. java基础集合类——ArrayList 源码略读

    ArrayList是java的动态数组,底层是基于数组实现. 1. 成员变量 public class ArrayList<E> extends AbstractList<E> ...

  4. react面试题——理解setState(源码object.assign)

    setState是异步的方式 this.setState({     counter:this.state.counter+1 }) console.log(this.state.counter) s ...

  5. 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目

    前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...

  6. 从源码的角度看 React JS 中批量更新 State 的策略(下)

    这篇文章我们继续从源码的角度学习 React JS 中的批量更新 State 的策略,供我们继续深入学习研究 React 之用. 前置文章列表 深入理解 React JS 中的 setState 从源 ...

  7. React躬行记(16)——React源码分析

    React可大致分为三部分:Core.Reconciler和Renderer,在阅读源码之前,首先需要搭建测试环境,为了方便起见,本文直接采用了网友搭建好的环境,React版本是16.8.6,与最新版 ...

  8. Redux源码学习笔记

    https://github.com/reduxjs/redux 版本 4.0.0 先了解一下redux是怎么用的,此处摘抄自阮一峰老师的<Redux 入门教程> // Web 应用是一个 ...

  9. 带着问题看redux源码

    前言 作为前端状态管理器,这个比较跨时代的工具库redux有很多实现和思想值得我们思考.在深入源码之前,我们可以相关注下一些常见问题,这样带着问题去看实现,也能更加清晰的了解. 常见问题 大概看了下主 ...

随机推荐

  1. linux 判断变量是否相等方法

    echo $? 输出上一个命令执行成功与否的情况 1表示失败 0 表示成功 test检测文件类型和比较值 有空格时等号才是判断,否则为赋值

  2. Odoo Session In Redis

    # odoo session in redis # 一.下载安装Session in Redis免费模块 # 下载地址:https://apps.odoo.com/apps/modules/12.0/ ...

  3. 精心整理16条MySQL使用规范,减少80%问题,推荐分享给团队

    上篇文章介绍了如何创建合适的MySQL索引,今天再一块学一下如何更规范.更合理的使用MySQL? 合理规范的使用MySQL,可以大大减少开发工作量和线上问题,并提升SQL查询性能. 我精心总结了这16 ...

  4. Win10 x64 安装Eplan P8 2.7 小结

    一.软件安装准备及过程 为免版权纠纷,此处不提供下载链接,请自行查找资源. 1.打开"Electric P8 2.7.3.11418"目录,以管理员身份运行"setup. ...

  5. Pulsar Summit Asia 2020 中文专场议题出炉!

    关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ...

  6. ceph 006 rbd高级特性 rbd快照 镜像克隆 rbd缓存 rbd增量备份 rbd镜像单向同步

    版本 [root@clienta ~]# ceph -v ceph version 16.2.0-117.el8cp (0e34bb74700060ebfaa22d99b7d2cdc037b28a57 ...

  7. Express 使用 Cookie

    在使用 Cookie 之前,需要给 Express 加载中间件,cookie-parser: npm i cookie-parser Express 使用中间件: import express fro ...

  8. 一、JDK和JRE

    JDK和JRE JDK=JRE+开发工具包: JRE=JVM+核心类库 如果只是运行Java程序,安装JRE即可:开发Java程序并运行则需要安装JDK.目前最稳定版本是JDK8.0,并且马上部分企业 ...

  9. [CF1500E] Subset Trick (平衡树)

    题面 洛谷翻译 V a n y a \rm Vanya Vanya 有一个初始大小为 n n n 的集合 S S S 和 q q q 次往集合加数/删数的操作.(集合中每个数字不同) 称一个数 x x ...

  10. Cannot resolve method 'println(java.lang.String)'

    jsp文件中println爆红 <% int sum = 0; for (int i = 1; i <=100 ; i++) { sum+=i; } out.println("& ...