封装Echarts组件

构建配置文件,按需引入相关组件

// echarts.config.js
// * 需要哪些组件和配置,请在 import 时手动添加。
import * as echarts from 'echarts/core';
// 引入用到的图表
import { BarChart, PieChart } from 'echarts/charts';
// 引入提示框、数据集等组件
import {
  DataZoomComponent,
  GridComponent,
  LegendComponent,
  TitleComponent,
  TooltipComponent,
} from 'echarts/components';
// 引入标签自动布局、全局过渡动画等特性
import { LabelLayout } from 'echarts/features';
// 引入 Canvas 渲染器,必须
import { CanvasRenderer } from 'echarts/renderers';
// 引入词云
import 'echarts-wordcloud';

// 注册必须的组件
echarts.use([
  BarChart,
  PieChart,
  TitleComponent,
  TooltipComponent,
  DataZoomComponent,
  LegendComponent,
  GridComponent,
  CanvasRenderer,
  LabelLayout,
]);

export default echarts;

封装Echart组件

import React, { useEffect, useImperativeHandle, useRef } from 'react';
import echarts from './config';

interface Props {
  options: any;
  onClick?: (params: any) => void;
}

//用React.forwardRef暴露自身节点给父组件
const EChart: React.ForwardRefExoticComponent<
  Props & React.RefAttributes<any>
> = React.forwardRef(({ options, onClick }, ref) => {
  //通过ref节点获取dom节点
  //如果用id,则每个Echart组件都为同个id,导致多次调用实际调用同一个组件
  const cDom = useRef<any>(null);
  //echart实例
  const cInstance = useRef<any>(null);

  //echart图表重新构建尺寸
  const resize = () => {
    cInstance.current.resize({
      animation: { duration: 300 },
    });
  };

  // 获取实例方法
  const getInstance = () => cInstance.current;

  //初次渲染
  useEffect(() => {
    //获取Dom节点
    cInstance.current = echarts.getInstanceByDom(cDom.current);
    //判断是否已经存在节点,无节点则初始化图表
    if (!cInstance.current) cInstance.current = echarts.init(cDom.current);

    //设定图表配置项,渲染图表
    //利用定时器,解决初次渲染和resize()后尺寸不一致问题
    setTimeout(() => {
      if (options) cInstance.current?.setOption(options);
      resize();
    }, 1);

    //绑定点击事件
    cInstance.current?.on('click', (event: Event) => {
      if (event && onClick) onClick(event);
    });

    //卸载时接触事件绑定和销毁图表实例
    return () => {
      cInstance.current?.off('click');
      cInstance.current?.dispose();
    };
  }, []);

  //监听options,重新渲染图表
  useEffect(() => {
    cInstance.current?.setOption(options);
  }, [options]);

  //监听resize,重新渲染图表
  useEffect(() => {
    window.addEventListener('resize', resize);

    return () => {
      window.removeEventListener('resize', resize);
    };
  }, [options]);

  //暴露getInstance方法给父组件
  useImperativeHandle(ref, () => ({ getInstance }));

  return <div ref={cDom} style={{ width: '100%', height: '100%' }} />;
});

//利用memo构建组件,优化性能
export default React.memo(EChart);

 

posted @ 2024-08-01 15:16  Karle  阅读(28)  评论(0编辑  收藏  举报