我遇到的问题是:使用sortable.js插件进行拖拽列表,列表里使用了echarts插件,多次拖拽同一个echarts会导致echarts内容丢失
使用的技术栈:angular12、sortableJs、echarts
这是我echarts的ts
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { DemandService } from '../demand.service';
import * as echarts from 'echarts';
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'ori-echarts',
templateUrl: './echarts.component.html',
styleUrls: ['./echarts.component.less']
})
export class EchartsComponent implements OnInit, AfterViewInit {
constructor(private ds: DemandService) { }
@Input() options;
@ViewChild('chartContainer') chartContainer!: ElementRef;
chartInstance
ngOnInit(): void {}
ngAfterViewInit(): void {
this.initEcahrts();
}
echartsInstanceIds = [];
initEcahrts() {
this.updateEcharts('init');
}
refreshEcharts() {
this.updateEcharts('refresh');
}
updateEcharts(optionType: 'init'|'refresh') {
const chartElement = document.createElement('div');
chartElement.style.width = '100%';
chartElement.style.height = '100%';
chartElement.id = 'ec_' + new Date().getTime();
if(optionType === 'refresh') {
if (this.chartContainer.nativeElement.querySelector('div')) {
this.chartContainer.nativeElement.querySelector('div').remove();
}
}
this.chartContainer.nativeElement.appendChild(chartElement);
this.chartInstance = echarts.init(chartElement);
this.chartInstance.setOption(this.options);
this.chartInstance.resize();
}
}
这是我echarts的html
<div #chartContainer style="width: 100%; height: 100%;"></div>
我在拖拽文件里写了如下代码片段
addProxyBindingCopyDrag() {
this.ds.proxySortableListDom = document.getElementById('proxy-sort-list');
const that = this;
const sortable = Sortable.create(this.ds.proxySortableListDom, {
group: {
name: 'proxyDrag',
pull: 'clone',
put: false
},
removeCloneOnHide: false,
filter: '.has-dragged-item',
animation: 150,
sort: false,
onStart: (evt) => {
const index = evt.clone.getAttribute('index');
this.dppChartComponent.refreshEcharts();
},
onEnd: (evt) => {
const index = evt.clone.getAttribute('index');
if (!that.ds.proxyList[index].dragged) {
that.ds.proxyList[index].dragged = true;
}
this.dppChartComponent.refreshEcharts();
}
});
}
结果第一次拖拽是好的
但到了第二次拖拽同一个图的时候
我本来以为是echarts的实例id相同的问题,但是现在的实现效果,每一次拖拽过来的echarts图实现了_echarts_instance_不同了,echarts还是会丢失
现在我不太清楚问题出在哪里了,请各位指点迷津!
【以下回答由 GPT 生成】
根据提供的代码,我们可以看到问题出现在拖拽同一个echarts图表时丢失内容。主要原因是每次拖拽都在重新创建一个echarts实例,但是并没有销毁之前的实例,导致页面上存在多个实例,并且重复调用resize方法可能会出现问题。
解决这个问题的关键在于正确创建和销毁echarts实例,并且避免重复调用resize方法。
首先,我们需要在EchartsComponent组件中添加一个销毁echarts实例的方法,并在组件销毁的时候调用该方法。
import { OnDestroy } from '@angular/core';
// ...
export class EchartsComponent implements OnInit, AfterViewInit, OnDestroy {
// ...
ngOnDestroy(): void {
this.destroyEcharts();
}
destroyEcharts() {
if (this.chartInstance) {
this.chartInstance.dispose();
this.chartInstance = null;
}
}
}
在拖拽文件的代码中,我们需要修改refreshEcharts方法,当echarts实例存在时才调用resize方法。
refreshEcharts() {
if (this.dppChartComponent.chartInstance) {
this.dppChartComponent.chartInstance.resize();
}
}
原先的initEcahrts方法在每次重新渲染组件时都会调用,导致创建多个echarts实例。我们需要在创建echarts实例前判断是否已经存在实例,如果存在则直接调用setOption方法更新数据。
initEcahrts() {
if (!this.chartInstance) {
this.createEcharts();
} else {
this.chartInstance.setOption(this.options);
this.chartInstance.resize();
}
}
createEcharts() {
const chartElement = document.createElement('div');
chartElement.style.width = '100%';
chartElement.style.height = '100%';
chartElement.id = 'ec_' + new Date().getTime();
if (this.chartContainer.nativeElement.querySelector('div')) {
this.chartContainer.nativeElement.querySelector('div').remove();
}
this.chartContainer.nativeElement.appendChild(chartElement);
this.chartInstance = echarts.init(chartElement);
this.chartInstance.setOption(this.options);
this.chartInstance.resize();
}
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { DemandService } from '../demand.service';
import * as echarts from 'echarts';
@Component({
selector: 'ori-echarts',
templateUrl: './echarts.component.html',
styleUrls: ['./echarts.component.less']
})
export class EchartsComponent implements OnInit, AfterViewInit, OnDestroy {
constructor(private ds: DemandService) { }
@Input() options;
@ViewChild('chartContainer') chartContainer!: ElementRef;
chartInstance;
ngOnInit(): void {
}
ngAfterViewInit(): void {
this.initEcahrts();
}
ngOnDestroy(): void {
this.destroyEcharts();
}
echartsInstanceIds = [];
initEcahrts() {
if (!this.chartInstance) {
this.createEcharts();
} else {
this.chartInstance.setOption(this.options);
this.chartInstance.resize();
}
}
createEcharts() {
const chartElement = document.createElement('div');
chartElement.style.width = '100%';
chartElement.style.height = '100%';
chartElement.id = 'ec_' + new Date().getTime();
if (this.chartContainer.nativeElement.querySelector('div')) {
this.chartContainer.nativeElement.querySelector('div').remove();
}
this.chartContainer.nativeElement.appendChild(chartElement);
this.chartInstance = echarts.init(chartElement);
this.chartInstance.setOption(this.options);
this.chartInstance.resize();
}
destroyEcharts() {
if (this.chartInstance) {
this.chartInstance.dispose();
this.chartInstance = null;
}
}
refreshEcharts() {
if (this.chartInstance) {
this.chartInstance.resize();
}
}
}
通过以上修改,我们解决了在拖拽同一个echarts图表时导致内容丢失的问题。主要是通过正确创建和销毁echarts实例,并避免重复调用resize方法来解决冲突。希望对你有所帮助!