第15章:ECharts 图表事件交互(若依 Vue3)

第15章:ECharts 图表事件交互(若依 Vue3)

业务场景:点击柱状图柱子 / 饼图扇区,拿到当前点击的数据,弹出弹窗、跳转页面,后台管理看板高频使用。基于上一节封装好的 useEcharts 组合式函数,新增事件绑定。

1、修改 @/composables/echartHelper.js,新增事件绑定能力

复制代码
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import * as echarts from 'echarts'

// 防抖工具函数
function debounce(fn, delay = 300) {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

export function useEcharts() {
  const chartRef = ref(null)
  let chartInstance = null
  let instanceReadyResolve = null
  const instanceReady = new Promise(resolve => {
    instanceReadyResolve = resolve
  })

  // 初始化图表
  const initChart = async () => {
    await nextTick()
    if (!chartRef.value) return
    chartInstance = echarts.init(chartRef.value)
    instanceReadyResolve()
  }

  const setChartOption = async (option) => {
    await instanceReady
    if (!chartInstance) return
    chartInstance.setOption(option, { notMerge: true })
  }

  const resizeChart = () => {
    chartInstance && chartInstance.resize()
  }
  const debounceResize = debounce(resizeChart, 300)

  // ✅ 新增:绑定echarts事件
  const onChartEvent = async (eventName, callback) => {
    await instanceReady
    chartInstance.on(eventName, callback)
  }

  // ✅ 新增:解绑echarts事件,防止内存泄露
  const offChartEvent = (eventName, callback) => {
    if(chartInstance){
      chartInstance.off(eventName, callback)
    }
  }

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

  onUnmounted(() => {
    window.removeEventListener('resize', debounceResize)
    if (chartInstance) {
      chartInstance.dispose()
      chartInstance = null
    }
  })

  return {
    chartRef,
    setChartOption,
    resizeChart,
    onChartEvent,
    offChartEvent
  }
}

2、页面组件完整代码(带点击事件,使用 Element Plus 弹窗)

复制代码
<template>
  <div class="chart-container">
    <el-alert title="点击柱状图柱子,弹出详情弹窗" type="info" style="margin-bottom:10px"/>
    <div
      ref="chartRef"
      style="width:100%;height:400px;border:1px solid #eee"
    ></div>

    <!-- 详情弹窗 -->
    <el-dialog v-model="dialogVisible" title="点击图表详情">
      <p>类别:{{ clickData.name }}</p>
      <p>数值:{{ clickData.value }}</p>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useEcharts } from '@/composables/echartHelper'
const { chartRef, setChartOption, onChartEvent } = useEcharts()

const dialogVisible = ref(false)
const clickData = ref({ name:'', value:0 })

const option = {
  title: { text: '图表点击事件测试' },
  xAxis: { type: 'category', data: ['周一','周二','周三','周四','周五'] },
  yAxis: { type: 'value' },
  series: [{ type: 'bar', data: [120, 200, 150, 80, 70] }]
}

// 渲染图表
setChartOption(option)

// 绑定点击事件
onChartEvent('click', (params)=>{
  console.log('点击参数', params)
  clickData.value = {
    name: params.name,
    value: params.value
  }
  dialogVisible.value = true
})
</script>

✅ 测试步骤

  1. 保存 echartHelper.js 和页面 vue 文件,刷新页面
  2. 柱状图正常渲染
  3. 点击柱子,弹出弹窗,展示当前柱子的名称和数值;控制台打印 params 对象
  4. 窗口缩放,防抖 resize 正常生效
  5. 切换路由离开页面,事件自动随实例销毁,不会残留事件监听
相关推荐
高级程序源7 小时前
SSM仓储管理系统31582-计算机课程设计、毕业设计
vue.js·python·mysql·小程序·flask·课程设计
溪语流沙7 小时前
【Web全栈进阶】前端世界观:现代工具链与框架为什么存在
前端·javascript·vue.js
WeiXin_DZbishe8 小时前
基于微信小程序的本地闲置物品交易平台-计算机毕设 附源码【课程设计】26825
vue.js·spring boot·python·微信小程序·架构·php·课程设计
高级程序源9 小时前
springboot本地生活服务平台33399-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·小程序·flask·课程设计
高级程序源9 小时前
springboot社区旧物回收管理系统25381-计算机课程设计、毕业设计
vue.js·spring boot·python·django·课程设计
高级程序源9 小时前
springboot大学生体测系统72170-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·django·课程设计
WeiXin_DZbishe9 小时前
基于Node.js的马拉松赛事管理系统的设计与实现-计算机毕设 附源码【课程设计】90211
java·javascript·vue.js·python·php·课程设计
风早爽太10 小时前
Mac 搭建 Vue 开发环境
前端·vue.js
高级程序源10 小时前
springboot校园外卖平台13676-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·tomcat·maven·课程设计
高级程序源11 小时前
springboot荆州旅游推介平台24175-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·django·课程设计