echart图表组件封装(vue3)

组件封装:

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>
相关推荐
番茄小能手几秒前
【全网唯一】C# 纯本地离线文字识别Windows版dll插件
开发语言·c#
梁诚斌19 分钟前
使用OpenSSL接口读取pem编码格式文件中的证书
开发语言·c++
瓜子三百克37 分钟前
Objective-C 路由表原理详解
开发语言·ios·objective-c
幽蓝计划1 小时前
HarmonyOS NEXT仓颉开发语言实战案例:外卖App
开发语言·harmonyos
孤水寒月1 小时前
给自己网站增加一个免费的AI助手,纯HTML
前端·人工智能·html
CoderLiu1 小时前
用这个MCP,只给大模型一个figma链接就能直接导出图片,还能自动压缩上传?
前端·llm·mcp
伍哥的传说1 小时前
鸿蒙系统(HarmonyOS)应用开发之实现电子签名效果
开发语言·前端·华为·harmonyos·鸿蒙·鸿蒙系统
海的诗篇_2 小时前
前端开发面试题总结-原生小程序部分
前端·javascript·面试·小程序·vue·html
小张成长计划..2 小时前
数据结构-栈的实现
开发语言·数据结构
uncleTom6662 小时前
前端地图可视化的新宠儿:Cesium 地图封装实践
前端