Echarts图表的二次封装
我们在做大屏可视化项目的时候,每次都要去声明一个变量,然后init这个图表,然后有变更,又去setOption,假如一个页面有10个图表,我们就要重复去操作10次,那么有没有可能去封装一个Echarts,我们只需要传相关的options进去,他就会自动帮我们做这些操作呢
先给大家封装了之后,使用起来多么的简单
<template>
<div class="caseContent">
<Echarts :options="options" v-if="data.length !== 0" />
<a-empty v-else />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import Echarts from './common/echarts.vue';
const options = computed(() => {
return xxxxx
})
</script>
代码是不是特别简洁,而且外部options变化了之后,里面的组件会自动执行setOption来更新图表。
下面我们就来看看如何封装这个Echarts图表吧
<template>
<div ref="chartRef" :style="{ width: chartWidth, height: chartHeight }"> </div>
</template>
<script setup lang="ts">
import { onMounted, onBeforeUnmount, onUpdated, ref, watch } from 'vue';
import * as echarts from 'echarts';
const props = defineProps({
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
options: {
type: Object,
required: true
}
});
let myCharts = null;
const chartRef = ref();
const chartWidth = ref(props.width);
const chartHeight = ref(props.height);
function initChart() {
if (!myCharts) {
myCharts = echarts.init(chartRef.value);
myCharts.setOption(props.options);
} else {
updateChart();
}
}
function updateChart() {
if (myCharts) {
myCharts.setOption(props.options);
}
}
watch(
() => props.options,
() => {
updateChart();
},
{ deep: true }
);
onMounted(() => {
initChart();
});
onUpdated(() => {
if (myCharts) {
myCharts.resize();
}
});
onBeforeUnmount(() => {
if (myCharts) {
myCharts.dispose();
}
});
</script>
<style scoped lang="less">
</style>
给大家举个例子,接口数据,可以自行mock
<template>
<div class="caseContent">
<Echarts :options="options" v-if="data.length !== 0" />
<a-empty v-else />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import Echarts from './common/echarts.vue';
const data = ref([]);
const options = computed(() => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
crossStyle: {
color: '#999'
},
label: {
backgroundColor: '#6a7985'
}
},
formatter: '{b} : {c}'
},
xAxis: {
type: 'category',
boundaryGap: false,
show: true,
axisLabel: {
textStyle: {
color: '#fff'
}
},
axisTick: {
show: false
},
data: data.value.map((item) => {
return item.report_time;
})
},
yAxis: {
type: 'value',
splitLine: {
show: false
},
axisLabel: {
textStyle: {
color: '#fff'
}
},
minInterval: 1
},
grid: {
containLabel: true,
top: 20,
left: 40,
right: 40,
bottom: 10
},
series: [
{
data: data.value.map((item) => {
return item.count;
}),
type: 'line',
lineStyle: {
color: '#1795FF',
width: 2
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0.1,
color: 'rgba(64, 175, 239, 0.2)'
},
{
offset: 1,
color: 'rgba(64, 175, 239, 0)'
}
]
}
}
}
]
};
});
</script>