父组件
<template>
<AbnormalAlarmStatistics ref="abnormalAlarmStatistics" />
</template>
<script setup>
import {
ref,
reactive,
computed,
onMounted,
getCurrentInstance,
watch
} from "vue";
const { proxy } = getCurrentInstance();
const getQualityAnalysisHistory = () => {
// 异常预警统计
let warningData = [
{
id: 1,
name: "预警1",
value: 0,
},
{
id: 2,
name: "预警2",
value: 0,
},
...
{
id: 40,
name: "预警40",
value: 0,
},
];
proxy.$refs["abnormalAlarmStatistics"].initChart(warningData);
};
onMounted(() => {
getQualityAnalysisHistory();
});
</script>
子组件
<template>
<el-card shadow="never" class="statistics">
<h4>异常报警统计</h4>
<div ref="chart" class="chart" style="width: 100%; height: 310px;"></div>
</el-card>
</template>
<script setup>
import { getCurrentInstance, ref } from "vue";
import * as echarts from "echarts";
import { useEcharts } from "@/hooks/useEcharts.js";
/**
* 初始化值
*/
const { proxy } = getCurrentInstance();
const initChart = (type) => {
let myChart = echarts.init(proxy.$refs.chart);
// 图表数据
const chartData = ref(type);
//总数
let sum = chartData.value.reduce((a, b) => {
return a + b.value;
}, 0);
let option = {
tooltip: {
trigger: "item",
},
legend: [
{
icon: "rect",
top: 20,
right: '12%',
itemHeight: 10,
itemWidth: 10,
itemGap: 14,
type: 'scroll',
orient: "vertical",
pageIconColor: '#1b9aee', //翻页下一页的三角按钮颜色
pageIconInactiveColor: '#7f7f7f', //翻页(即翻页到头时)
data: chartData.value.map((v) => v.name),
textStyle: {
rich: {
uname: {
color: "#333333",
fontSize: 14,
width: 80
},
unum: {
color: "#333333",
fontWeight: "bold",
fontSize: 14,
align: "right",
},
},
},
formatter(name) {
let res = chartData.value.filter((v) => v.name == name);
return `{uname|${name}}{unum|${res[0].value}}`;
},
}
],
color: [
"#0058FF",
"#D33232",
"#FFFF02",
"#FF9402",
"#00EBFF",
"#FFC608",
"#00AF75",
"#9E46DE",
"#F06856",
"#0BB1D0",
],
series: [
{
type: "pie",
radius: [65, 80],
center: ["30%", "45%"],
avoidLabelOverlap: false,
label: {
normal: {
show: true,
position: "center",
color: "#4c4a4a",
formatter: "{total|" + sum + "}" + "\n\r" + "{active|报警总数(次)}",
rich: {
total: {
fontSize: 20,
color: "#333333",
fontWeight: "bold",
},
active: {
fontSize: 14,
color: "#333333",
padding: [7, 0, 0, 0],
},
},
},
emphasis: {
//中间文字显示
show: true,
},
},
labelLine: {
show: false,
},
itemStyle: {
borderWidth: 0,
borderColor: "#fff",
},
data: chartData.value,
},
],
};
useEcharts(myChart, option);
};
defineExpose({ initChart });
</script>
<style lang="scss" scoped>
.statistics {
height: 364px;
}
</style>
公共方法,用于图表 resize 和 销毁
useEcharts.js
import { onBeforeUnmount, onDeactivated } from "vue";
// import * as echarts from "echarts";
/**
* @description 使用 Echarts (只是为了添加图表响应式)
* @param {Element} myChart Echarts实例 (必传)
* @param {Object} options 绘制Echarts的参数 (必传)
* */
// 全局ECharts实例的容器
let globalEChartsInstances = new Set();
export const useEcharts = (myChart, options) => {
if (options && typeof options === "object") {
myChart.setOption(options,true);
globalEChartsInstances.add(myChart);
}/* */
const echartsResize = () => {
myChart && myChart.resize();
};
window.addEventListener("resize", echartsResize);
// 防止 echarts 页面 keepAlive 时,还在继续监听页面
onDeactivated(() => {
window.removeEventListener("resize", echartsResize);
});
// onBeforeUnmount(() => {
// window.removeEventListener("resize", echartsResize);
// myChart.dispose()
// });
};
// 销毁所有ECharts实例的函数
export const destroyAllECharts = () => {
globalEChartsInstances.forEach(chart => {
chart.dispose();
});
globalEChartsInstances.clear();
}
//*暴露所有的echarts实例
export default globalEChartsInstances;
全局监听路由变化,销毁图表
router.beforeEach(async (to, from, next) => {
//*当前路由和跳转路由不一致时,有echarts实例就销毁
if(to.path !== from.path) {
if(globalEChartsInstances?.size > 0) destroyAllECharts(); // 当即将离开当前路由时销毁全
局ECharts实例
}
}
});