本文记录我使用echarts踩的坑,问题主要还是对echarts文档不熟悉,因为公司项目不方便展示,我用一个小demo做演示。
需求:点击选项或下拉框,要求echarts根据选项渲染不同的数据。
需求效果如下
第一次实现这样的效果,我是通过创建两个实例,通过下拉框的value控制实例的隐藏,从而实现这样的效果。
const charts1 = useRef();
const charts2 = useRef();
const [value,setValue] = useState('1')
const option1 ={...};
const option2 ={...};
useEffect(()=>{
if(value=='1'){
const chart1=echarts.init(charts1.current);
chart1.setOption(option1)
}else {
const chart2=echarts.init(charts2.current);
chart2.setOption(option2)
}
},[value])
return (
<div className="App" style={{paddingTop:300}}>
<div style={{width:'100%',height:300}}>
<Select style={{width:150}} value={value} onSelect={(value)=>{setValue(value)}}>
<Option value={'1'}>图一</Option>
<Option value={'2'}>图二</Option>
</Select>
{value=='1'?<div ref={charts1} style={{width:'100%',height:'100%'}}></div>:null}
{value=='2'?<div ref={charts2} style={{width:'100%',height:'100%'}}></div>:null}
</div>
</div>
);
上面的写法是一种解决办法,但是如果选项很多的话,不可能每一个都创建一个实例,所以上面的方法很鸡肋;然后我又想了一种方法,echarts的布局是不变的,那么我们是否可以只创建一个实例,只在这个实例上更新不同的echarts配置项。
useEffect(()=>{
const chart1=echarts.init(charts1.current);
if(value=='1'){
chart1.setOption(option1)
}else{
chart1.setOption(option2)
}
},[value])
return (
<div className="App" style={{paddingTop:300}}>
<div style={{width:'100%',height:300}}>
<Select style={{width:150}} value={value} onSelect={(value)=>{setValue(value)}}>
<Option value={'1'}>图一</Option>
<Option value={'2'}>图二</Option>
</Select>
<div ref={charts1} style={{width:'100%',height:'100%'}}></div>
</div>
</div>
);
我将代码修改成只有一个实例, 通过setOption更新对应的echarts数据,但是出现了一下效果
原本的option1有两条数据,option2只有一条数据,所以切换选项时,应该是两条数据变成一条数据,可结果却是图一的一条数据保留了下来,污染了图二,这个问题如果解决呢?
如果对官方文档很熟悉,其实这里的解决办法就很简单,可我是个菜鸡,找了很久才知道,如果新的配置项中包含原来不存在的数据系列或数据点,它们会被添加到图表中。而如果新的配置项中包含了和原来相同数据系列和数据点的设置,那么它们会被替换成新的设置。但是,如果新的配置项没有包含原先的数据系列或数据点,它们不会被自动删除。因此,原来的数据依然存在于图表中并且可见。
简单解释就是新的配置项有原来存在的数据系列,就会替换原来的数据系列,新的配置项没有原来的数据系列,就会将原来的数据系列合并到新的数据系列。
echarts官方文档中解释了setOption,其中第二个参数noMerge表示是否不跟之前设置的option进行合并,默认是false,如果设置为true,则表示会删除上一个option,然后根据新的option创建新的组件。
将第二个参数设置为true,就可以实现我们预期的效果了。