封装v-echarts
按需加载重点: 通过 echartsComponents 参数接受Echarts组件
<template>
<div class="v-echarts">
<div ref="chartRef" style="width: 100%; height: 100%; margin: 0 auto;"></div>
<el-empty class="echarts-empty" v-if="isEmpty"></el-empty>
</div>
</template>
<script lang="ts">
import { defineComponent, nextTick, onUnmounted, ref } from 'vue'
import { downloadFile } from '@/utils'
import * as echarts from 'echarts/core'
import { GridComponent, TooltipComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([GridComponent, TooltipComponent, CanvasRenderer])
export default defineComponent({
name: 'v-echarts',
props: {
echartsComponents: {
type: Array,
default: () => []
},
option: {
type: Object,
default: () => ({})
},
isEmpty: {
type: Boolean,
default: false
}
} as any,
setup (props) {
echarts.use(props.echartsComponents)
const resizeChart = (el:any, myChart:any) => {
const myObserver:any = new ResizeObserver(() => {
const width = el.parentElement.offsetWidth * 0.9
if (myChart) myChart.resize({ width: el.offsetWidth > width ? el.offsetWidth : width })
})
myObserver.observe(el)
return myObserver
}
const chartRef = ref()
let myChart: any = null // echarts 实例
let observer: any = null // observer 实例
const clear = () => {
if (myChart) {
myChart.dispatchAction({ type: 'hideTip' }) // 清除tootip
myChart.dispose() // 清空当前实例
}
if (observer) observer.disconnect()
}
// 初始化 echarts
const init = (option = {}) => {
clear()
nextTick(() => {
const el = chartRef.value
myChart = echarts.init(el)
setOption(option)
observer = resizeChart(el, myChart)
})
}
const setOption = (option = {} as any) => myChart && myChart.setOption({
backgroundColor: '#ffffff', // 背景色
series: [],
grid: { left: '80', right: '80', top: '40', bottom: '40'},
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value' },
...option,
}, true)
onUnmounted(() => {
clear()
})
return {
chartRef,
init,
setOption,
download (name = '下载') {
downloadFile(myChart.getDataURL(), name)
}
}
}
})
</script>
<style lang="scss" scoped>
.v-echarts {
position: relative;
width: 100%;
height: 100%;
.echarts-empty {
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
width: 100%;
height: 100%;
background: #fff;
}
}
</style>
组件使用
业务组件只需关注
option
及组件的初始化和渲染
<template>
<v-echarts
v-loading="loading"
ref="vEchartsRef"
style="height: 330px;"
:echartsComponents="echartsComponents"
:isEmpty="echartsData.length === 0"
></v-echarts>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue'
import vEcharts from '@/components/v-echarts.vue'
import { LineChart } from 'echarts/charts'
import { LegendComponent } from 'echarts/components'
export default defineComponent({
name: 'trend-chart',
components: { vEcharts },
setup (props) {
const vEchartsRef = ref()
const option = {
color: ['#50B1FC', '#50D1A6', '#F2B63F'],
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
yAxis: {},
series: [{
data: [],
type: "line"
}]
}
const renderChart = () => {
option.series[0].data = [820, 932, 901, 934, 1290, 1330, 1320]
vEchartsRef.value.setOption(option)
}
const init = () => {
vEchartsRef.value.init(option)
}
onMounted(()=> {
init()
})
return {
init,
renderChart,
echartsComponents: [LineChart, LegendComponent]
}
}
})
</script>
<style lang="scss" scoped></style>