在开发过程中,我发现项目的很多地方会用到echarts图,因为如果每个echarts单独写的话,感觉很麻烦,所以我就直接使用组件的形式,把一个echarts用组件的形式封装起来,然后里面的数据就由父组件传值进去,子组件(即这个echarts组件)接收,但是在开发过程中,我遇到了一个问题,就是多图的时候,我使用遍历数组的形式,然后传id给echarts组件,发现组件里面的resize()其他三个图无效,只有最后一个生效,这个问题困扰了我很久,上网查资料找答案,发现网上的答案,都是使用把多图的每个id拿出来初始化,然后每个id进行resize(),这样确实有效果,但是问题是我是遍历的,而不是每个图都是独立的,都是由id传进来,所以我自己想了一个方法,就是定义一个数组,然后把这个初始化的echarts的实例push进这个数组去,最后要进行resize()的时候,对这个数组进行遍历,然后每个进行resize()即可。
代码如下:
这个是组件的代码,命名为chart.vue
<template>
<div :id="id" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from 'echarts';
require('echarts/theme/macarons'); // echarts theme
import { debounce } from '@/utils/tools';
let chart = null;
export default {
// mixins: [resize],
props: {
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '460px',
},
// 线性图的id
id: {
type: String,
default: '',
},
// 里面内容
dataLegend: {
type: Array,
default: () => [],
},
// 横坐标内容
dataListChart: {
type: Array,
default: () => [],
},
// 线形图里面的数据
seriesDataChart: {
type: Array,
default: () => [],
},
// 悬浮框
tooltip: {
type: Object,
default: () => {},
},
},
data() {
return {
// chart: null,
$_sidebarElm: null,
$_resizeHandler: null,
echartsAll: [],
};
},
mounted() {
this.$_resizeHandler = debounce(() => {
if (chart) {
// console.log('this.echartsAll',this.echartsAll);
// console.log('chart',chart);
for (let i = 0; i < this.echartsAll.length; i++) {
this.echartsAll[i].resize();
}
// chart.resize();
}
}, 100);
this.$_initResizeEvent();
this.$_initSidebarResizeEvent();
this.$nextTick(() => {
setTimeout(this.initChart, 300);
});
},
activated() {
this.$_initResizeEvent();
this.$_initSidebarResizeEvent();
},
deactivated() {
this.$_destroyResizeEvent();
this.$_destroySidebarResizeEvent();
},
beforeUnmount() {
this.$_destroyResizeEvent();
this.$_destroySidebarResizeEvent();
if (!chart) {
return;
}
chart.dispose();
chart = null;
},
computed: {},
methods: {
initChart() {
// chart = echarts.init(this.$el, 'macarons');
// if (chart != null && chart != '' && chart != undefined) {
// chart.dispose(); //销毁
// }
chart = echarts.init(document.getElementById(this.id));
this.echartsAll.push(chart);
// this.$store.state.user.echartsAll.push(chart);
chart.setOption(
{
// title: {
// text: 'Stacked Area Chart',
// },
tooltip: this.tooltip,
legend: {
data: this.dataLegend,
// data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine'],
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
// 横坐标内容
data: this.dataListChart,
},
],
yAxis: [
{
type: 'value',
},
],
series: this.seriesDataChart,
},
true
);
},
$_initResizeEvent() {
window.addEventListener('resize', this.$_resizeHandler);
},
$_destroyResizeEvent() {
window.removeEventListener('resize', this.$_resizeHandler);
},
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.$_resizeHandler();
}
},
$_initSidebarResizeEvent() {
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0];
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler);
},
$_destroySidebarResizeEvent() {
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler);
},
},
};
</script>
然后是父组件代码,也就是引用以上的组件的代码:
<template>
<div class="dashboard">
<el-row :gutter="30">
<el-col :span="12" v-for="(item, index) in testReportList" :key="index">
<div class="item">
<div class="b">
<FootPanelGroupVue :report="item.report"></FootPanelGroupVue>
<div v-for="(item2, indey) in item.charts" :key="indey">
<AreaChartVue
:id="item.id"
:dataLegend="dataLegend"
:seriesDataChart="item2.seriesDataChart"
:dataListChart="item2.dataListChart"
:tooltip="item2.tooltip"
></AreaChartVue>
</div>
<div class="report-title">{{ item.title }}</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import FootPanelGroupVue from '@/views/dashboard/components/FootPanelGroup.vue';
import AreaChartVue from '@/components/AreaChart/chart.vue';
import { getGeneral, getReportChart } from '@/api';
export default {
name: 'Dashboard',
components: {
BasePage,
BarChart,
CountTo,
PanelGroup,
TestParamTable,
TestReportTable,
TestFailTable,
TestFailRateTable,
FootPanelGroupVue,
AreaChartVue,
},
data() {
return {
typeList: [],
typeTextList: [],
levelList: [],
levelTextList: [],
statOrg: {},
statStaff: {},
// statOrgCert: { innerLevel1: [], innerLevel2: [], outerLevel1: [], outerLevel2: [] },
innerLevel1: [],
innerLevel2: [],
outerLevel1: [],
outerLevel2: [],
statSigner: {},
xText: [],
flag: false,
dataList: ['岩土工程类', '混凝土工程类', '金属结构类', '机械电气类', '量测类'],
dataLegend: ['合格报告数', '不合格报告数', '其他报告数量'],
seriesList: [], // 柱状图的数据
// 悬浮窗
tooltip: {},
// 堆叠图的数据
seriesDataConstruction: [], // 施工方
seriesDataParallel: [], // 平行检
seriesDataThird: [], // 第三方检
seriesDataSupervise: [], // 监督检
// 堆叠图的横坐标内容
dataListConstruction: [], // 施工方
dataListParallel: [], // 平行检
dataListThird: [], // 第三方检
dataListSupervise: [], // 监督检
// 堆叠图的纵坐标数据内容
// 施工方
dataConstructionReportYaxis: [],
dataConstructionPassYaxis: [],
dataConstructionFailYaxis: [],
dataConstructionOtherYaxis: [],
// 平行检
dataParallelReportYaxis: [],
dataParallelPassYaxis: [],
dataParallelFailYaxis: [],
dataParallelOtherYaxis: [],
// 第三方检
dataThirdReportYaxis: [],
dataThirdPassYaxis: [],
dataThirdFailYaxis: [],
dataThirdOtherYaxis: [],
// 监督检
dataSuperviseReportYaxis: [],
dataSupervisePassYaxis: [],
dataSuperviseFailYaxis: [],
dataSuperviseOtherYaxis: [],
// 概览
headDataList: [],
activeName: 'testParam',
// 四张堆叠图数据
testReportList: [],
// 堆叠图数据
dataResult: [],
};
},
methods: {
// 获取报告图标数据
async getReportChartData() {
const res = await getReportChart.fn({});
// console.log('获取报告图标数据是', res);
if (res.code == 0) {
this.dataResult = res.data;
this.getChartData();
} else {
this.$message.warning(res.message);
}
},
// 获取报告数量
getReportChart() {
// 施工方
this.seriesDataConstruction = [
{
name: '合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataConstructionPassYaxis,
},
{
name: '不合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataConstructionFailYaxis,
},
{
name: '其他报告数量',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataConstructionOtherYaxis,
},
];
// 平行检
this.seriesDataParallel = [
{
name: '合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataParallelPassYaxis,
},
{
name: '不合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataParallelFailYaxis,
},
{
name: '其他报告数量',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataParallelOtherYaxis,
},
];
// 第三方检
this.seriesDataThird = [
{
name: '合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataThirdPassYaxis,
},
{
name: '不合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataThirdFailYaxis,
},
{
name: '其他报告数量',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataThirdOtherYaxis,
},
];
// 监督检
this.seriesDataSupervise = [
{
name: '合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataSupervisePassYaxis,
},
{
name: '不合格报告数',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataSuperviseFailYaxis,
},
{
name: '其他报告数量',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series',
},
data: this.dataSuperviseOtherYaxis,
},
];
this.tooltip = {
trigger: 'axis',
// axisPointer: {
// type: 'cross',
// label: {
// backgroundColor: '#6a7985',
// },
// },
formatter: function (params, ticket, callback) {
let htmlStr = '';
let counts = 0;
let xName = '';
for (let i = 0; i < params.length; i++) {
let param = params[i].data;
xName = params[i].name;
counts = Number(param) + counts;
}
htmlStr += '<div style="font-size:14px; color: #666; font-weight: 400; line-height: 1; margin:5px 0px;">';
htmlStr += xName;
htmlStr += '</div>';
htmlStr += '<div>';
htmlStr += '<span style="margin-right:5px;display:inline-block;width:10px;height:10px;border-radius:10px;background-color:violet;"></span>';
htmlStr +=
'<span style="font-size:14px; color:#666; font-weight:400; margin-left:2px">报告总数量:</span><span style="float:right; text-align:right; margin-left:20px; font-size: 14px; color: #666; font-weight:900">' +
counts +
' 个</span>';
htmlStr += '<div style="clear: both;"></div>';
htmlStr += '</div>';
for (let i = 0; i < params.length; i++) {
// console.log('总的数据是', params[i]);
let param = params[i].data;
let seriesName = params[i].seriesName;
let value = param; //y轴值
let color = params[i].color;
htmlStr += '<div>';
htmlStr +=
'<span style="margin-right:5px;display:inline-block;width:10px;height:10px;border-radius:10px;background-color:' + color + ';"></span>';
htmlStr +=
'<span style="font-size:14px; color:#666; font-weight:400; margin-left:2px">' +
seriesName +
':</span>' +
'<span style="float:right; margin-left:20px; font-size: 14px; color: #666; font-weight:900">' +
value +
' 个</span>';
htmlStr += '<div style="clear: both;"></div>';
htmlStr += '</div>';
}
return htmlStr;
},
};
},
getChartList() {
return [
{
report: [
{
reportTitle: '报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格率',
reportNum: '0',
},
],
title: '施工方自检情况',
id: 'main',
charts: [
{
seriesDataChart: this.seriesDataConstruction,
dataListChart: this.dataListConstruction,
tooltip: this.tooltip,
},
],
},
{
report: [
{
reportTitle: '报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格率',
reportNum: '0',
},
],
title: '平行检情况',
id: 'second',
charts: [
{
seriesDataChart: this.seriesDataParallel,
dataListChart: this.dataListParallel,
tooltip: this.tooltip,
},
],
},
{
report: [
{
reportTitle: '报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格率',
reportNum: '0',
},
],
title: '第三方检情况',
id: 'three',
charts: [
{
seriesDataChart: this.seriesDataThird,
dataListChart: this.dataListThird,
tooltip: this.tooltip,
},
],
},
{
report: [
{
reportTitle: '报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格报告数量',
reportNum: 0,
addNum: 0,
},
{
reportTitle: '不合格率',
reportNum: '0',
},
],
title: '监督检情况',
id: 'four',
charts: [
{
// dataLegend: ['合格报告数', '不合格报告数', '其他报告数量'],
seriesDataChart: this.seriesDataSupervise,
dataListChart: this.dataListSupervise,
tooltip: this.tooltip,
},
],
},
];
},
// 堆叠图数据整理
getChartData() {
this.dataResult.forEach((item) => {
// console.log('数据item是', item);
if (item.testingType == 0) {
let testReportCount = '';
let testReportFailCount = '';
let testReportOtherCount = '';
let testReportPassCount = '';
let failRate = '';
// 遍历返回的数据
item.statistical.chartData.forEach((itemChart) => {
testReportCount = Number(itemChart.testReportCount) + Number(testReportCount);
testReportFailCount = Number(itemChart.testReportFailCount) + Number(testReportFailCount);
testReportPassCount = Number(itemChart.testReportPassCount) + Number(testReportPassCount);
testReportOtherCount = Number(itemChart.testReportOtherCount) + Number(testReportOtherCount);
itemChart.month = itemChart.month.substring(0, 7);
this.dataListConstruction.push(itemChart.month);
this.dataConstructionPassYaxis.push(testReportPassCount);
this.dataConstructionFailYaxis.push(testReportFailCount);
this.dataConstructionOtherYaxis.push(testReportOtherCount);
});
// 把服务器组装完之后的数据放到自己的数组中
this.testReportList.forEach((itemList) => {
if (itemList.title == '施工方自检情况') {
itemList.report.forEach((itemReport) => {
if (itemReport.reportTitle == '报告数量') {
itemReport.addNum = item.statistical.testReportRecentCount;
itemReport.reportNum = testReportCount;
} else if (itemReport.reportTitle == '不合格报告数量') {
itemReport.addNum = item.statistical.testReportRecentFailCount;
itemReport.reportNum = testReportFailCount;
} else if (itemReport.reportTitle == '不合格率') {
if (testReportCount == 0 || testReportFailCount == 0) {
itemReport.reportNum = 0;
} else {
failRate = ((testReportFailCount / testReportCount) * 100).toFixed(1);
itemReport.reportNum = failRate + '%';
}
}
});
}
});
} else if (item.testingType == 1) {
let testReportCount = '';
let testReportFailCount = '';
let failRate = '';
let testReportOtherCount = '';
let testReportPassCount = '';
// 遍历返回的数据
item.statistical.chartData.forEach((itemChart) => {
testReportCount = Number(itemChart.testReportCount) + Number(testReportCount);
testReportFailCount = Number(itemChart.testReportFailCount) + Number(testReportFailCount);
testReportPassCount = Number(itemChart.testReportPassCount) + Number(testReportPassCount);
testReportOtherCount = Number(itemChart.testReportOtherCount) + Number(testReportOtherCount);
itemChart.month = itemChart.month.substring(0, 7);
this.dataListParallel.push(itemChart.month);
this.dataParallelPassYaxis.push(testReportPassCount);
this.dataParallelFailYaxis.push(testReportFailCount);
this.dataParallelOtherYaxis.push(testReportOtherCount);
});
// 把服务器组装完之后的数据放到自己的数组中
this.testReportList.forEach((itemList) => {
if (itemList.title == '平行检情况') {
itemList.report.forEach((itemReport) => {
if (itemReport.reportTitle == '报告数量') {
itemReport.addNum = item.statistical.testReportRecentCount;
itemReport.reportNum = testReportCount;
} else if (itemReport.reportTitle == '不合格报告数量') {
itemReport.addNum = item.statistical.testReportRecentFailCount;
itemReport.reportNum = testReportFailCount;
} else if (itemReport.reportTitle == '不合格率') {
if (testReportCount == 0 || testReportFailCount == 0) {
itemReport.reportNum = 0;
} else {
failRate = ((testReportFailCount / testReportCount) * 100).toFixed(1);
itemReport.reportNum = failRate + '%';
}
}
});
}
});
} else if (item.testingType == 3) {
let testReportCount = '';
let testReportFailCount = '';
let failRate = '';
let testReportOtherCount = '';
let testReportPassCount = '';
// 遍历返回的数据
item.statistical.chartData.forEach((itemChart) => {
testReportCount = Number(itemChart.testReportCount) + Number(testReportCount);
testReportFailCount = Number(itemChart.testReportFailCount) + Number(testReportFailCount);
testReportPassCount = Number(itemChart.testReportPassCount) + Number(testReportPassCount);
testReportOtherCount = Number(itemChart.testReportOtherCount) + Number(testReportOtherCount);
itemChart.month = itemChart.month.substring(0, 7);
this.dataListThird.push(itemChart.month);
this.dataThirdPassYaxis.push(testReportPassCount);
this.dataThirdFailYaxis.push(testReportFailCount);
this.dataThirdOtherYaxis.push(testReportOtherCount);
});
// 把服务器组装完之后的数据放到自己的数组中
this.testReportList.forEach((itemList) => {
if (itemList.title == '第三方检情况') {
itemList.report.forEach((itemReport) => {
if (itemReport.reportTitle == '报告数量') {
itemReport.addNum = item.statistical.testReportRecentCount;
itemReport.reportNum = testReportCount;
} else if (itemReport.reportTitle == '不合格报告数量') {
itemReport.addNum = item.statistical.testReportRecentFailCount;
itemReport.reportNum = testReportFailCount;
} else if (itemReport.reportTitle == '不合格率') {
if (testReportCount == 0 || testReportFailCount == 0) {
itemReport.reportNum = 0;
} else {
failRate = ((testReportFailCount / testReportCount) * 100).toFixed(1);
itemReport.reportNum = failRate + '%';
}
}
});
}
});
} else if (item.testingType == 4) {
let testReportCount = '';
let testReportFailCount = '';
let failRate = '';
let testReportOtherCount = '';
let testReportPassCount = '';
// 遍历返回的数据
item.statistical.chartData.forEach((itemChart) => {
testReportCount = Number(itemChart.testReportCount) + Number(testReportCount);
testReportFailCount = Number(itemChart.testReportFailCount) + Number(testReportFailCount);
testReportPassCount = Number(itemChart.testReportPassCount) + Number(testReportPassCount);
testReportOtherCount = Number(itemChart.testReportOtherCount) + Number(testReportOtherCount);
itemChart.month = itemChart.month.substring(0, 7);
this.dataListSupervise.push(itemChart.month);
this.dataSupervisePassYaxis.push(testReportPassCount);
this.dataSuperviseFailYaxis.push(testReportFailCount);
this.dataSuperviseOtherYaxis.push(testReportOtherCount);
});
// 把服务器组装完之后的数据放到自己的数组中
this.testReportList.forEach((itemList) => {
if (itemList.title == '监督检情况') {
itemList.report.forEach((itemReport) => {
if (itemReport.reportTitle == '报告数量') {
itemReport.addNum = item.statistical.testReportRecentCount;
itemReport.reportNum = testReportCount;
} else if (itemReport.reportTitle == '不合格报告数量') {
itemReport.addNum = item.statistical.testReportRecentFailCount;
itemReport.reportNum = testReportFailCount;
} else if (itemReport.reportTitle == '不合格率') {
if (testReportCount == 0 || testReportFailCount == 0) {
itemReport.reportNum = 0;
} else {
failRate = ((testReportFailCount / testReportCount) * 100).toFixed(1);
itemReport.reportNum = failRate + '%';
}
}
});
}
});
}
});
},
},
mounted() {
// 父组件自适应
// let echarts = this.$store.state.user.echartsAll;
// window.onresize = function () {
// for (let i = 0; i < echarts.length; i++) {
// echarts[i].resize();
// }
// };
// setTimeout(this.fetchData, 3000);
// 概览数据
this.headDataList = this.getGeneralListData();
this.getGeneralData();
// 检测机构资质
this.fetchData();
this.getReportChartData();
// 堆叠图数据
this.getReportChart();
this.testReportList = this.getChartList();
},
};
</script>
以上就是差不多的整体代码,有点多,但是其中最重要的还是在组件chart.vue中的几行代码,在data中定义数组echartsAll: [],
data() {
return {
echartsAll: [],
};
},
然后再初始化chart中,
chart = echarts.init(document.getElementById(this.id));
this.echartsAll.push(chart);
最后在mounted中遍历这个数组,然后进行resize()才有效
import { debounce } from '@/utils/tools';
menthods:{
$_initResizeEvent() {
window.addEventListener('resize', this.$_resizeHandler);
},
},
mounted(){
this.$_resizeHandler = debounce(() => {
if (chart) {
// console.log('this.echartsAll',this.echartsAll);
// console.log('chart',chart);
for (let i = 0; i < this.echartsAll.length; i++) {
this.echartsAll[i].resize();
}
// chart.resize();
}
}, 100);
}
在其中有两行console.log()代码打印出来,你会发现第一个打印出来的每个chart的id都是不一样的,而第二个打印出来的id都是一样的,而且都是最后一个chart图的id,这也就是为什么是最后一图生效,而其他图不生效的原因所在。
以上就是我关于resize()在遍历中只有最后一张图的自适应生效的理解和解决办法,如果大佬有更好的解决办法,欢迎大佬的建议和评价,谢谢大佬们的阅读。