Vue2 /Vue3 + ECharts

4 阅读2分钟

最清晰、最实用、企业级标准写法Vue2 + EChartsVue3 + ECharts 两套完整代码,直接复制就能跑,包含:

  • 封装通用图表组件
  • 深色主题
  • 自适应窗口
  • 实时刷新
  • 多图表(折线、柱状、饼图)

一、Vue2 + ECharts 完整版

1. 安装

npm install echarts@4.9.0 --save

2. 全局引入(main.js)

import Vue from 'vue'
import App from './App.vue'
import * as echarts from 'echarts'

Vue.prototype.$echarts = echarts
new Vue({
  render: h => h(App)
}).$mount('#app')

3. 封装 ECharts 通用组件(components/ChartBox.vue)

<template>
  <div :id="id" :style="style"></div>
</template>

<script>
export default {
  name: 'ChartBox',
  props: {
    id: { type: String, required: true },
    width: { type: String, default: '100%' },
    height: { type: String, default: '300px' },
    option: { type: Object, required: true }
  },
  data() {
    return {
      chart: null
    }
  },
  computed: {
    style() {
      return { width: this.width, height: this.height }
    }
  },
  watch: {
    option: {
      handler() {
        this.setOption()
      },
      deep: true
    }
  },
  mounted() {
    this.initChart()
    window.addEventListener('resize', this.resize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resize)
    this.chart?.dispose()
  },
  methods: {
    initChart() {
      this.chart = this.$echarts.init(document.getElementById(this.id), 'dark')
      this.setOption()
    },
    setOption() {
      this.chart?.setOption(this.option)
    },
    resize() {
      this.chart?.resize()
    }
  }
}
</script>

4. 页面使用(实时刷新+多图表)

<template>
  <div class="wrap">
    <ChartBox id="bar" height="300px" :option="barOption" />
    <ChartBox id="line" height="300px" :option="lineOption" />
    <ChartBox id="pie" height="300px" :option="pieOption" />
  </div>
</template>

<script>
import ChartBox from '@/components/ChartBox'
export default {
  components: { ChartBox },
  data() {
    return {
      barOption: {},
      lineOption: {},
      pieOption: {}
    }
  },
  mounted() {
    this.renderCharts()
    this.timer = setInterval(() => this.renderCharts(), 3000)
  },
  beforeDestroy() {
    clearInterval(this.timer)
  },
  methods: {
    randData() {
      return [120, 200, 150, 80, 70].map(v => v + Math.random() * 50)
    },
    renderCharts() {
      this.barOption = {
        title: { text: '柱状图' },
        xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
        yAxis: {},
        series: [{ type: 'bar', data: this.randData() }]
      }
      this.lineOption = {
        title: { text: '折线图' },
        xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
        yAxis: {},
        series: [{ type: 'line', data: this.randData() }]
      }
      this.pieOption = {
        title: { text: '饼图' },
        series: [{
          type: 'pie',
          radius: ['30%', '60%'],
          data: [
            { value: 300, name: 'A' },
            { value: 200, name: 'B' },
            { value: 150, name: 'C' }
          ]
        }]
      }
    }
  }
}
</script>

<style scoped>
.wrap {
  background: #081022;
  padding: 20px;
}
</style>

二、Vue3 + ECharts 完整版(Composition API)

1. 安装

npm install echarts --save

2. 封装通用组件(components/ChartBox.vue)

<template>
  <div :id="id" :style="style"></div>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount, computed } from 'vue'
import * as echarts from 'echarts'

const props = defineProps({
  id: { type: String, required: true },
  width: { type: String, default: '100%' },
  height: { type: String, default: '300px' },
  option: { type: Object, required: true }
})

const chart = ref(null)
const style = computed(() => ({ width: props.width, height: props.height }))

const initChart = () => {
  chart.value = echarts.init(document.getElementById(props.id), 'dark')
  chart.value.setOption(props.option)
}

const resize = () => chart.value?.resize()

watch(() => props.option, (val) => {
  chart.value?.setOption(val)
}, { deep: true })

onMounted(() => {
  initChart()
  window.addEventListener('resize', resize)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resize)
  chart.value?.dispose()
})
</script>

3. 页面使用(多图表+实时刷新)

<template>
  <div class="wrap">
    <ChartBox id="bar" height="280px" :option="barOption" />
    <ChartBox id="line" height="280px" :option="lineOption" />
    <ChartBox id="pie" height="280px" :option="pieOption" />
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import ChartBox from '@/components/ChartBox'

const barOption = ref({})
const lineOption = ref({})
const pieOption = ref({})
let timer = null

const randData = () => [120, 200, 150, 80, 70].map(v => v + Math.random() * 50)

const render = () => {
  barOption.value = {
    title: { text: 'Vue3 柱状图' },
    xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
    yAxis: {},
    series: [{ type: 'bar', data: randData() }]
  }
  lineOption.value = {
    title: { text: 'Vue3 折线图' },
    xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
    yAxis: {},
    series: [{ type: 'line', smooth: true, data: randData() }]
  }
  pieOption.value = {
    title: { text: 'Vue3 饼图' },
    series: [{
      type: 'pie', radius: ['30%', '60%'],
      data: [
        { value: 335, name: 'A' },
        { value: 310, name: 'B' },
        { value: 234, name: 'C' }
      ]
    }]
  }
}

onMounted(() => {
  render()
  timer = setInterval(render, 3000)
})

onBeforeUnmount(() => clearInterval(timer))
</script>

<style scoped>
.wrap {
  background: #081022;
  padding: 20px;
}
</style>

三、核心亮点(企业标准)

  1. 封装通用组件,一次封装,全项目复用
  2. 深色主题init(..., 'dark')
  3. 响应式自适应
  4. watch 监听数据自动更新
  5. 定时器实时刷新
  6. 销毁自动清理,防止内存泄漏
  7. 支持所有图表:折线、柱状、饼图、地图、仪表盘