众所周知,echarts的使用经常会涉及到大量重复的代码,那么封装一个hook来,将重复的代码放在一块,可以节省很多大代码书写。
useCharts
首先要搞清楚echarts需要什么。
- 一个Dom节点。
- 配置Option。
我们需要什么。
- echarts的实例,方便操作echarts
1、大体的结构。
那么我们的大概了解hook需要的参数 option 和返回的内容:生成的echarts的实例对象。但是echarts初始化需要用到dom 那么我们就需要在hook里放ref。
const useChart = (option) => {
const chart = useRef(null);
let chartInstance= useRef(null);
//...
return [chart,chartInstance]
}
2、生成的echarts的实例对象。
接下来,我们要初始化得到chartInstance ===> echarts.init(chart.current),但是我们知道,要等组件挂载完毕后才可以获取到Dom,那么init就需要放在UseEffect中,并且要在组件卸载时销毁,那么就需要这样写。
const useChart = (option) => {
const chart = useRef(null);
let chartInstance= useRef(null);
useEffect(() => {
chartInstance= echarts.init(chart.current);
chartInstance.setOption(option)
return () => {
//卸载时销毁
chartInstance && chartInstance.dispose()
}
}, [option]);
//由于钩子一开始的chartInstance为null,会在使用的时候定义下来,获取不到最新的实例对象,所以要写一个get函数代替实例
const getInstance = () => {
return chartInstance
}
return [chart,getInstance]
}
3、配置一些默认的option
由于一个项目echarts的配置项和样式大致时相同的,所以可以把一些特定的option写为常量,setOption的时候合并一下会更方便。
import * as echarts from 'echarts'
import {useEffect, useRef} from "react";
import {merge} from "lodash";
const DEFAUTL_OPTION = {
//一些默认的配置项
tooltip: {},
xAxis: {
axisLabel: {}
},
yAxis: {},
series: {
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: '#a7d1ff',
},
type: 'bar',
},
}
const useChart = (option) => {
const chart = useRef(null);
let chartInstance = useRef(null);
useEffect(() => {
chartInstance = echarts.init(chart.current);
//这里使用的merge合并对象用的是lodash的,也可以自己写一个合并函数
chartInstance .setOption(merge(DEFAUTL_OPTION, option))
return () => {
myChart && myChart.dispose()
}
}, [option]);
const getInstance = () => {
return chartInstance
}
return [chart, getInstance]
}
4、使用
const Chart = memo(() => {
const [chart, getInstance] = useChart({
//由于配置了默认的配置项 所以这里就可以只关注数据
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
series: {
data: [5, 20, 36, 10, 10, 20]
},
})
const handleClick = () => {
//通过 钩子函数返回的 getInstance方法就可以成功拿到实例对象,就可以对echarts做一些变化了
getInstance().setOption(
{
series: [
{
type: 'bar',
data: [111, 200, 36, 10, 10, 20]
}
]
})
}
return (
<div>
<Button onClick={handleClick.run}>
切换
</Button>
<div
ref={chart}
style={{
height: 400,
width: 400,
}}
className={'size-full rounded-lg bg-gray-50 shadow-lg mt-20'}
></div>
</div>
);
})