React之echarts-for-react源码解读

目录
  • 前言
  • 从与原生初始化对比开始
  • 陷阱-默认值height为300px
  • 主逻辑源码剖析
    • 挂载渲染过程
    • 更新渲染过程
    • 卸载过程
  • 项目依赖
  • 后续

前言

在当前工业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),特点如下:

  • 采用PureComponent方式编写组件以便适配所有React版本;
  • 仅对ECharts 命令式API进行声明式API的封装,并没有将每种EChart图表类型封装为组件;
  • 添加特性,监测容器尺寸的变化,并自动调用ECharts实例的resize方法实现自适应。

挂载渲染过程

  • componentDidMount时调用renderNewEcharts方法执行ECharts组件的生成逻辑;
  • renderNewEcharts方法内部逻辑

    通过echarts.getInstanceByDom(容器DOM元素)echarts.init(容器DOM元素,主题,配置)获取已有ECharts实例或生成新的ECharts实例;

    通过ECharts实例的setOption方法设置或更新图表内容;

    通过ECharts实例的showLoadinghideLoading控制图表渲染前是否显示加载进度条;

    将通过props onEvents配置的ECharts支持的事件处理器绑定到ECharts实例上;

    触发props onChartsReady 方法;

    订阅通过size-sensor监测容器尺寸并自动调用ECharts实例的resize方法,实现图表尺寸的自适应。

更新渲染过程

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

  • 若更新的props包含themeoptsonEvents则要销毁原来的ECharts实例,重新构建一个新的ECharts实例,并终止更新渲染过程;否则执行第2步。
  • 若props中的option,notMergela,lazyUpdate,showLoadingloadingOption均没有变化,则不更新ECharts实例;
    注意:EChartsReactCore继承PureComponent,若上述props进行shallow equal比较为true时也不会更新ECharts实例;但这一步采用deep equal比较,来减少ECharts实例的更新。
  • 若props中的styleclassName发生变化则会触发ECharts实例的resize方法。

卸载过程

  • 取消通过size-sensor订阅的容器尺寸变化事件;
  • 通过ECharts实例的dispose方法注销ECharts实例。

项目依赖

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

后续

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

到此这篇关于React之echarts-for-react源码解读的文章就介绍到这了,更多相关echarts-for-react源码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 探究react-native 源码的图片缓存问题

    本文为xcode模拟器测试,rn版本0.44.3 突然想学习下RN是如何封装ios中的UIImage的,看着看着发现图片的缓存问题是个坑... 先看js端图片使用的三种方式,依次排序1.2.3 <Image source={{uri:url}} style={{width:200,height:200}}/> // 1. 加载远程图片 <Image source={{uri:'1.png'}} style={{width:50,height:50}}/> //2.加载xcode中图

  • 用React-Native+Mobx做一个迷你水果商城APP(附源码)

    前言 最近一直在学习微信小程序,在学习过程中,看到了 wxapp-mall 这个微信小程序的项目,觉得很不错,UI挺小清新的,便clone下来研究研究,在看源码过程中,发现并不复杂,用不多的代码来实现丰富的功能确实令我十分惊喜,于是,我就想,如果用react-native来做一个类似这种小项目难不难呢,何况,写一套代码还能同时跑android和ios(小程序也是...),要不写一个来玩玩?有了这个想法,我便直接 react-native init 一个project来写一下吧(๑•̀ㅂ•́)و✧

  • 深入理解react-router@4.0 使用和源码解析

    如果你已经是一个正在开发中的react应用,想要引入更好的管理路由功能.那么,react-router是你最好的选择~ react-router版本现今已经到4.0.0了,而上一个稳定版本还是2.8.1.相信我,如果你的项目中已经在使用react-router之前的版本,那一定要慎重的更新,因为新的版本是一次非常大的改动,如果你要更新,工作量并不小. 这篇文章不讨论版本的变化,只是讨论一下React-router4.0的用法和源码. 源码在这里:https://github.com/ReactT

  • React 源码调试方式

    目录 正文 断点调试 搜索定位 Chrome Devtools 调试 sourcemap npm 下载react包 插件注释 调试 React 最初源码 关联 react 源码项目 总结 正文 什么?调试 React 源码还有优雅和不优雅之分? 别着急,我们先来听个故事: 东东是一名前端工程师,主要用 React 技术栈,用了多年之后想深入一下,所以最近开始看 React 源码. 断点调试 他把 react 和 react-dom 包下载了下来,在项目里引入,开发服务跑起来后,打开 Chrome

  • 浅谈react-router@4.0 使用方法和源码分析

    react-router-dom@4.3.0 || react-router@4.4.1 react-router 使用方法 配置 router.js import React, { Component } from 'react'; import { Switch, Route } from 'react-router-dom'; const router = [{ path: '/', exact: true, component:importPath({ loader: () => imp

  • react 源码中位运算符的使用详解

    位运算符基本使用 按位与(&):a & b对于每一个比特位,两个操作数都为 1 时, 结果为 1, 否则为 0 按位或(|):a | b对于每一个比特位,两个操作数都为 0 时, 结果为 0, 否则为 1 按位异或(^):a ^ b对于每一个比特位,两个操作数相同时, 结果为 1, 否则为 0 按位非(~):~ a反转操作数的比特位, 即 0 变成 1, 1 变成 0 0000 0000 0000 0000 0000 0000 0000 0011 -> 3 1111 1111 111

  • 使用VScode 插件debugger for chrome 调试react源码的方法

    代码调试,是我们前端日常工作中不可或缺的能力了吧! 在面向dom开发的时代,我们开发时直接在chrome里打断点是很方便的. 但是,当我们面向组件开发时(react),浏览器拿到的是我们编译过后的代码,还想在浏览器里打断点几乎是不可能的了. 场景 那怎么办,方法总是比困难多!愚蠢的我想到了console/debugger!!一直在使用,虽然很不方便(打印太多实在太乱!上线还要配置删除掉),但是我竟然使用了很久(这真是一个糟糕的编码习惯吧).直到今天,我想研究一下react源码,需要断点的地方有很

  • React之echarts-for-react源码解读

    目录 前言 从与原生初始化对比开始 陷阱-默认值height为300px 主逻辑源码剖析 挂载渲染过程 更新渲染过程 卸载过程 项目依赖 后续 前言 在当前工业4.0和智能制造的产业升级浪潮当中,智慧大屏无疑是展示企业IT成果的最有效方式之一.然而其背后怎么能缺少ECharts的身影呢?对于React应用而言,直接使用ECharts并不是最高效且优雅的方式,而echarts-for-react则是针对React应用对ECharts进行轻量封装和增强的工具库. echarts-for-react的

  • React前端开发createElement源码解读

    目录 React 与 Babel 元素标签转译 组件转译 子元素转译 createElement 源码 函数入参 第一段代码 __self 和 __source 第二段代码 props 对象 第三段代码 children 第四段代码 defaultProps 第五段代码 owner ReactElement 源码 REACT_ELEMENT_TYPE 回顾 React 与 Babel 元素标签转译 用过 React 的同学都知道,当我们这样写时: <div id="foo">

  • 通过示例源码解读React首次渲染流程

    目录 说明 题目 首次渲染流程 render beginWork completeUnitOfWork commit 准备阶段 before mutation 阶段 mutation 阶段 切换 Fiber Tree layout 阶段 题目解析 总结 说明 本文结论均基于 React 16.13.1 得出,若有出入请参考对应版本源码.参考了 React 技术揭秘. 题目 在开始进行源码分析前,我们先来看几个题目: 题目一: 渲染下面的组件,打印顺序是什么? import React from

  • React实时预览react-live源码解析

    目录 引言 源码解读 输入内容 Provider generateElement 其他组件 总结 引言 react-live 是一个 react 的实时编辑器,可直接编辑 react 代码,并实时预览.可以看下官方的预览图: 本文针对的源码版本 src ├── components │ ├── Editor │ │ └── index.js │ └── Live │ ├── LiveContext.js │ ├── LiveEditor.js │ ├── LiveError.js │ ├── L

  • React Refs 的使用forwardRef 源码示例解析

    目录 三种使用方式 1. String Refs 2. 回调 Refs 3. createRef 两种使用目的 Refs 转发 createRef 源码 forwardRef 源码 三种使用方式 React 提供了 Refs,帮助我们访问 DOM 节点或在 render 方法中创建的 React 元素. React 提供了三种使用 Ref 的方式: 1. String Refs class App extends React.Component { constructor(props) { su

  • React实现合成事件的源码分析

    目录 事件绑定 事件触发 结尾 今天尝试学习 React 事件的源码实现. React 版本为 18.2.0 React 中的事件,是对原生事件的封装,叫做合成事件.抽象出一层合成事件,是为了做兼容,抹平不同浏览器之间的差异. 下面会从两个方面进行源码的解读: 事件绑定 事件触发 事件绑定 首先是 React 项目过程启动时,调用 listenToAllSupportedEvents 方法,做合成事件的绑定. // 对应方法 `ReactDOM.createRoot() function cre

  • React Context原理深入理解源码示例分析

    目录 正文 一.概念 二.使用 2.1.React.createContext 2.2.Context.Provider 2.3.React.useContext 2.4.Example 三.原理分析 3.1.createContext 函数实现 3.2. JSX 编译 3.3.消费组件 - useContext 函数实现 3.4.Context.Provider 在 Fiber 架构下的实现机制 3.5.小结 四.注意事项 五.对比 useSelector 正文 在 React 中提供了一种「

  • React深入分析更新的创建源码

    目录 ReactDom.render setState 与 forceUpdate expirationTime的作用 获取currentTime 不同的expirationTime React 的鲜活生命起源于 ReactDOM.render ,这个过程会为它的一生储备好很多必需品,我们顺着这个线索,一探婴儿般 React 应用诞生之初的悦然. 更新创建的操作我们总结为以下两种场景 ReactDOM.render setState forceUpdate ReactDom.render 串联该

  • vue3 源码解读之 time slicing的使用方法

    今天给大家带来一篇源码解析的文章,emm 是关于 vue3 的,vue3 源码放出后,已经有很多文章来分析它的源码,我觉得很快又要烂大街了,哈哈 不过今天我要解析的部分是已经被废除的 time slicing 部分,这部分源码曾经出现在 vue conf 2018 的视频中,但是源码已经被移除掉了,之后可能也不会有人关注,所以应该不会烂大街 打包 阅读源码之前,需要先进行打包,打包出一份干净可调试的文件很重要 vue3 使用的 rollup 进行打包,我们需要先对它进行改造 import cle

  • Vite项目自动添加eslint prettier源码解读

    目录 引言 使用 源码阅读 总结 引言 vite-pretty-lint库是一个为Vite创建的Vue或React项目初始化eslint和prettier的库. 该库的目的是为了让开发者在创建项目时,不需要手动配置eslint和prettier,而是通过vite-pretty-lint库来自动配置. 源码地址: vite-pretty-lint github1s 直接看 使用 根据vite-pretty-lint库的README.md,使用该库的只需要执行一行命令即可: // NPM npm i

随机推荐