日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React之echarts-for-react源碼解讀_React

作者:肥仔John ? 更新時間: 2022-11-25 編程語言

前言

在當前工業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包含theme,?optsonEvents則要銷毀原來的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源碼略讀》。

原文鏈接:https://www.cnblogs.com/fsjohnhuang/p/16792575.html

欄目分類
最近更新