组件封装:
<template><div class="echart-container"><div class="chart" ref="chartRef"></div></div>
</template><script lang="ts" setup>import { ref, nextTick, onMounted, watch, defineProps, defineExpose, computed } from 'vue'import * as echarts from 'echarts'import lodash from 'lodash'const props = defineProps({data: {type: Object,default() {return {title: '',series: [],xAxis: []}},},})const chartData = ref(props.data)let chartRef = ref(null)let myChart = nulllet defTitle = {text: '',textStyle: {fontSize: 16,fontWeight: 'none',color: '#999999',},left: 10,top: 10,}let defYA = {type: 'value',splitLine: {show: true,},axisTick: {show: true,},axisLine: {show: true,},axisLabel: {color: '#999999',},nameTextStyle: {color: '#999999',},minInterval: 1,}let defYAxis = [defYA,lodash.defaultsDeep({position: 'right',nameTextStyle: {padding: [0, 0, 20, 0],align: 'left',},axisLabel: {align: 'right',margin: 30,},},defYA,),]let yAxis = computed(() => {let val = props.data.yAxislet value = [defYAxis[0]]let arr = []if (Array.isArray(val) && val.length) {val.forEach((ele, index) => {let defObj = defYAxis[index] || valuelet obj = lodash.defaultsDeep(ele, defObj)arr.push(obj)})value = arr}return value})let defXAxis = {type: 'category',data: [],axisTick: {show: true,},splitLine: {show: false,},axisLine: {show: true,},axisLabel: {color: '#999999',},}let xAxis = computed(() => {let val = props.data.xAxislet value = defXAxisif (Array.isArray(val)) {value.data = val} else {value = lodash.defaultsDeep(val, value)}return value})let title = computed(() => {let val = defTitlelet tit = props.data.titleif (typeof tit === 'string') {val.text = tit} else {val = lodash.defaultsDeep(tit, val)}return val})const formatNumber = (num) => {return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}let option = ref({title: title.value,legend: {},tooltip: lodash.defaultsDeep(props.data.tooltip, {trigger: 'axis',formatter: (params) => {let html = params[0].namelet data = props.datafor (let i = 0, l = params.length; i < l; i++) {let unit = data.series[i].unit || data.unit || ''let color = data.series[i].colorhtml += `<div style="margin-top:5px;"><span style="float:left;">${params[i].marker}${params[i].seriesName}</span><span style="float:right;margin-left:20px;"><span style="margin-right:1px;">${formatNumber(params[i].value)}</span>${unit}</span><div style="clear:both;"></div><div>`}return html},}),grid: {left: '2%',right: '2%',bottom: '4%',containLabel: true,},toolbox: {},xAxis: xAxis.value,yAxis: yAxis.value,series: [],})const init = () => {myChart = echarts.init(chartRef.value)myChart.setOption(option.value)}const setData = () => {nextTick(() => {var data = chartData.valuelet xAxis = data.xAxisif (Array.isArray(xAxis)) {option.value.xAxis.data = xAxis} else {option.value.xAxis = xAxis}option.value.series = data.seriesmyChart.setOption(option.value)})}const resize = lodash.debounce(() => {myChart.resize()}, 200)onMounted(() => {init()window.onresize = function () {resize()}})watch(() => props.data,(val) => {chartData.value = valsetData()},{immediate: true,deep: true,},)defineExpose({chartRef,})
</script>
<style lang="scss" scoped>.echart-container {width: 100%;min-height: 200px;height: 100%;padding: 0 10px;box-sizing: border-box;.chart {height: 100%;width: 100%;}}
</style>
组件调用:
<template><my-chart :data="chartData"></my-chart>
</template>
<script lang="ts" setup>import myChart from '@/components/MyChart/index.vue'const chartData = ref({title:'标题',unit: '单位',series: [{name: '折线图',type: 'line',data: [],smooth: true,color: '#1B5CFF',},],xAxis: []})
</script>