封装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);