Skip to content

ECharts 图表

基于 ECharts 封装的图表组件,支持动态更新、自适应、主题切换等功能。

基础用法

最基础的图表展示用法。

vue
<template>
  <NVueEchart :option="chartOption" />
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

柱状图

vue
<template>
  <NVueEchart :option="chartOption" />
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar',
    },
  ],
})
</script>

饼图

vue
<template>
  <NVueEchart :option="chartOption" />
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  series: [
    {
      type: 'pie',
      radius: '50%',
      data: [
        { value: 1048, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Union Ads' },
        { value: 300, name: 'Video Ads' },
      ],
    },
  ],
})
</script>

动态更新

图表会自动监听 option 变化并更新。

vue
<template>
  <NVueEchart :option="chartOption" />
  <NButton @click="updateData">更新数据</NButton>
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const updateData = () => {
  chartOption.value = {
    ...chartOption.value,
    series: [
      {
        ...chartOption.value.series[0],
        data: [280, 190, 210, 180, 250, 170, 300],
      },
    ],
  }
}
</script>

自适应容器

设置 autoresize 属性使图表自适应容器大小。

vue
<template>
  <div style="width: 100%; height: 400px;">
    <NVueEchart :option="chartOption" autoresize />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

自定义尺寸

使用 widthheight 属性来设置图表尺寸。

vue
<template>
  <NVueEchart :option="chartOption" width="600px" height="400px" />
</template>

<script setup>
import { ref } from 'vue'

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

加载状态

设置 loading 属性来显示加载状态。

vue
<template>
  <NVueEchart :option="chartOption" :loading="loading" />
  <NButton @click="toggleLoading">切换加载状态</NButton>
</template>

<script setup>
import { ref } from 'vue')

const loading = ref(true)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const toggleLoading = () => {
  loading.value = !loading.value
}
</script>

空数据状态

设置 hasData 属性为 false 来显示空数据状态。

vue
<template>
  <NVueEchart :option="chartOption" :hasData="hasData" />
  <NButton @click="hasData = !hasData">切换数据状态</NButton>
</template>

<script setup>
import { ref } from 'vue')

const hasData = ref(true)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

SVG 渲染器

设置 renderer 属性为 'svg' 来使用 SVG 渲染器。

vue
<template>
  <NVueEchart :option="chartOption" renderer="svg" />
</template>

<script setup>
import { ref } from 'vue')

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

主题

使用 theme 属性来设置图表主题。

vue
<template>
  <NVueEchart :option="chartOption" theme="dark" />
</template>

<script setup>
import { ref } from 'vue')

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})
</script>

图表联动

使用 group 属性来实现多个图表之间的联动。

vue
<template>
  <div style="display: flex; gap: 20px;">
    <NVueEchart :option="chartOption1" group="myGroup" style="flex: 1;" />
    <NVueEchart :option="chartOption2" group="myGroup" style="flex: 1;" />
  </div>
</template>

<script setup>
import { ref } from 'vue')

const chartOption1 = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const chartOption2 = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [280, 190, 210, 180, 250, 170, 300],
      type: 'bar',
    },
  ],
})
</script>

不合并配置

设置 notMerge 属性为 true 来完全替换配置。

vue
<template>
  <NVueEchart :option="chartOption" :notMerge="true" />
  <NButton @click="switchChart">切换图表类型</NButton>
</template>

<script setup>
import { ref } from 'vue')

const isLine = ref(true)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const switchChart = () => {
  isLine.value = !isLine.value
  chartOption.value = {
    xAxis: {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    },
    yAxis: {
      type: 'value',
    },
    series: [
      {
        data: [150, 230, 224, 218, 135, 147, 260],
        type: isLine.value ? 'line' : 'bar',
      },
    ],
  }
}
</script>

事件监听

组件支持 readyresizeclick 等事件。

vue
<template>
  <NVueEchart
    :option="chartOption"
    @ready="handleReady"
    @resize="handleResize"
    @click="handleClick"
  />
</template>

<script setup>
import { ref } from 'vue')

const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const handleReady = (instance) => {
  console.log('图表已准备好:', instance)
}

const handleResize = (size) => {
  console.log('图表尺寸变化:', size)
}

const handleClick = (params) => {
  console.log('图表点击:', params)
}
</script>

获取图表实例

通过 ref 获取组件实例,调用 getInstance 方法获取 ECharts 实例。

vue
<template>
  <NVueEchart ref="chartRef" :option="chartOption" />
  <NButton @click="exportImage">导出图片</NButton>
</template>

<script setup>
import { ref } from 'vue')

const chartRef = ref(null)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const exportImage = () => {
  const instance = chartRef.value.getInstance()
  if (instance) {
    const url = instance.getDataURL({
      type: 'png',
      pixelRatio: 2,
      backgroundColor: '#fff',
    })
    console.log('图片 URL:', url)
  }
}
</script>

手动设置配置

通过 ref 获取组件实例,调用 setOption 方法手动设置配置。

vue
<template>
  <NVueEchart ref="chartRef" :option="chartOption" />
  <NButton @click="updateOption">更新配置</NButton>
</template>

<script setup>
import { ref } from 'vue')

const chartRef = ref(null)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const updateOption = () => {
  chartRef.value.setOption({
    series: [
      {
        data: [280, 190, 210, 180, 250, 170, 300],
      },
    ],
  })
}
</script>

手动触发 resize

通过 ref 获取组件实例,调用 resize 方法手动触发 resize。

vue
<template>
  <NVueEchart ref="chartRef" :option="chartOption" :autoresize="false" />
  <NButton @click="handleResize">手动 resize</NButton>
</template>

<script setup>
import { ref } from 'vue')

const chartRef = ref(null)
const chartOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line',
    },
  ],
})

const handleResize = () => {
  chartRef.value.resize()
}
</script>

API

Props

属性说明类型默认值
optionECharts 配置项ECOption | any
hasData是否有数据,用于显示空状态booleantrue
className根节点类名string
theme主题名称或主题对象string | Record<string, unknown>
autoresize父容器尺寸变化时是否自动触发图表 resizebooleantrue
renderer渲染器类型'canvas' | 'svg''canvas'
width图表容器的宽度string'100%'
height图表容器的高度string'360px'
loading是否显示加载状态booleanfalse
notMergesetOption 方法的 notMerge 参数,用于是否合并配置项booleanfalse
lazyUpdatesetOption 方法的 lazyUpdate 参数,用于是否延迟更新booleantrue
replaceMergesetOption 方法的 replaceMerge 参数,用于指定完全替换的配置部分string | string[]
group图表联动的 group 名称,用于实现多个图表之间的联动string

Events

事件名说明类型
ready图表实例创建完成后触发(instance: EChartsInstance) => void
resize图表触发尺寸调整时触发(size: { width: number; height: number }) => void
click图表触发点击事件时触发(params: unknown) => void

方法

方法名说明类型
getInstance获取当前的 ECharts 实例() => EChartsInstance | null
setOption设置图表配置,支持动态更新(option: ECOption, opts?: SetOptionOpts) => void
resize手动触发图表的 resize 方法(width?: number, height?: number) => void