组件封装:
javascript
<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 = null
let 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.yAxis
let value = [defYAxis[0]]
let arr = []
if (Array.isArray(val) && val.length) {
val.forEach((ele, index) => {
let defObj = defYAxis[index] || value
let 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.xAxis
let value = defXAxis
if (Array.isArray(val)) {
value.data = val
} else {
value = lodash.defaultsDeep(val, value)
}
return value
})
let title = computed(() => {
let val = defTitle
let tit = props.data.title
if (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].name
let data = props.data
for (let i = 0, l = params.length; i < l; i++) {
let unit = data.series[i].unit || data.unit || ''
let color = data.series[i].color
html += `<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.value
let xAxis = data.xAxis
if (Array.isArray(xAxis)) {
option.value.xAxis.data = xAxis
} else {
option.value.xAxis = xAxis
}
option.value.series = data.series
myChart.setOption(option.value)
})
}
const resize = lodash.debounce(() => {
myChart.resize()
}, 200)
onMounted(() => {
init()
window.onresize = function () {
resize()
}
})
watch(
() => props.data,
(val) => {
chartData.value = val
setData()
},
{
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>
组件调用:
javascript
<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>