echarts圖表點擊legend報錯問題(折線圖)

原因是:echats 實例,不能夠用響應式變量去接收。
在這里插入圖片描述

<template><div class="attendance-chart"><div v-if="loading" class="loading">加載中...</div><div v-else-if="error" class="error">數據加載失敗: {{ error }}<button @click="fetchData">重新加載</button></div><div v-else><div ref="chart" style="width: 100%; height: 350px;"></div><div v-if="!chartData.attendanceData.length" class="no-data">暫無數據</div></div></div>
</template><script>
import * as echarts from 'echarts';
import homeService from '@api/home/home';export default {name: 'AttendanceChart',data() {return {chartInstance: null,  //這里是響應式chartData: {projectList: [],dateList: [],attendanceData: [],},loading: false,error: null,};},mounted() {this.fetchData();window.addEventListener('resize', this.resizeChart);},beforeDestroy() {window.removeEventListener('resize', this.resizeChart);this.destroyChart();},methods: {async fetchData() {this.loading = true;this.error = null;try {const response = await homeService.getData();if (this.validateData(response)) {this.chartData = response;this.$nextTick(() => this.initChart());} else {throw new Error('數據格式不正確');}} catch (err) {this.error = err.message || '請求失敗';console.error('獲取數據失敗:', err);} finally {this.loading = false;}},validateData(data) {return (Array.isArray(data.projectList) &&Array.isArray(data.dateList) &&Array.isArray(data.attendanceData) &&data.attendanceData.every(item => item.projectName && Array.isArray(item.data) &&item.data.every(val => typeof val === 'number')));},initChart(attempt = 0) {if (attempt > 3) {this.error = '圖表初始化超時';return;}if (!this.$refs.chart) {setTimeout(() => this.initChart(attempt + 1), 200);return;}this.destroyChart();try {this.chartInstance = echarts.init(this.$refs.chart);this.updateChart();} catch (err) {console.error('圖表初始化失敗:', err);this.error = '圖表初始化失敗';}},updateChart() {if (!this.chartInstance) return;try {const option = {tooltip: {trigger: 'axis',backgroundColor: 'rgba(0,0,0,0.7)',borderWidth: 0,padding: 10,textStyle: {color: '#fff',fontSize: 12},},legend: {data: this.chartData.projectList,bottom: 10,textStyle: {fontSize: 12},},grid: {left: '3%',right: '4%',bottom: '15%',top: '5%',containLabel: true},xAxis: {type: 'category',boundaryGap: false,data: this.chartData.dateList,axisLabel: {rotate: 45,fontSize: 12}},yAxis: {type: 'value',name: '人數',nameTextStyle: {fontSize: 12}},series: this.chartData.attendanceData.map(item => ({name: item.projectName,type: 'line',data: item.data,symbol: 'circle',symbolSize: 6,showSymbol: false,lineStyle: {width: 2},emphasis: {lineStyle: {width: 3}}}))};this.chartInstance.setOption(option, true);} catch (err) {console.error('圖表配置失敗:', err);this.error = '圖表渲染失敗';}},resizeChart() {if (this.chartInstance) {this.chartInstance.resize();}},destroyChart() {if (this.chartInstance) {this.chartInstance.dispose();this.chartInstance = null;}}}
};
</script><style scoped>
.attendance-chart {width: 100%;height: 350px;padding: 12px;background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);position: relative;
}.loading,
.error,
.no-data {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);text-align: center;color: #666;
}.error {color: #f56c6c;
}.error button {margin-top: 8px;padding: 4px 12px;background: #f56c6c;color: white;border: none;border-radius: 4px;cursor: pointer;
}.no-data {color: #999;
}
</style>

修正后的代碼:

<template><div class="attendance-chart"><div v-if="loading" class="loading">加載中...</div><div v-else-if="error" class="error">數據加載失敗: {{ error }}<button @click="fetchData">重新加載</button></div><div v-else><div ref="chart" style="width: 100%; height: 350px;"></div><div v-if="!chartData.attendanceData.length" class="no-data">暫無數據</div></div></div>
</template><script>
import * as echarts from 'echarts';
import homeService from '../../../api/home/home';export default {name: 'AttendanceChart',data() {return {// 不要將 chartInstance 放在 data 中chartData: {projectList: [],dateList: [],attendanceData: [],},loading: false,error: null,};},// 將 chartInstance 作為組件實例屬性chartInstance: null,mounted() {this.fetchData();window.addEventListener('resize', this.resizeChart);},beforeDestroy() {window.removeEventListener('resize', this.resizeChart);this.destroyChart();},methods: {async fetchData() {this.loading = true;this.error = null;try {const response = await homeService.getData();if (this.validateData(response)) {this.chartData = response;this.$nextTick(() => this.initChart());} else {throw new Error('數據格式不正確');}} catch (err) {this.error = err.message || '請求失敗';console.error('獲取數據失敗:', err);} finally {this.loading = false;}},validateData(data) {return (Array.isArray(data.projectList) &&Array.isArray(data.dateList) &&Array.isArray(data.attendanceData) &&data.attendanceData.every(item => item.projectName && Array.isArray(item.data) &&item.data.every(val => typeof val === 'number')));},initChart(attempt = 0) {if (attempt > 3) {this.error = '圖表初始化超時';return;}if (!this.$refs.chart) {setTimeout(() => this.initChart(attempt + 1), 200);return;}this.destroyChart();try {// 直接賦值給組件實例屬性,而不是響應式數據this.$options.chartInstance = echarts.init(this.$refs.chart);this.updateChart();} catch (err) {console.error('圖表初始化失敗:', err);this.error = '圖表初始化失敗';}},updateChart() {// 從組件實例屬性獲取const chartInstance = this.$options.chartInstance;if (!chartInstance) return;try {const option = {tooltip: {trigger: 'axis',backgroundColor: 'rgba(0,0,0,0.7)',borderWidth: 0,padding: 10,textStyle: {color: '#fff',fontSize: 12},},legend: {data: this.chartData.projectList,bottom: 10,textStyle: {fontSize: 12},},grid: {left: '3%',right: '4%',bottom: '15%',top: '5%',containLabel: true},xAxis: {type: 'category',boundaryGap: false,data: this.chartData.dateList,axisLabel: {rotate: 45,fontSize: 12}},yAxis: {type: 'value',name: '人數',nameTextStyle: {fontSize: 12}},series: this.chartData.attendanceData.map(item => ({name: item.projectName,type: 'line',data: item.data,symbol: 'circle',symbolSize: 6,showSymbol: false,lineStyle: {width: 2},emphasis: {lineStyle: {width: 3}}}))};chartInstance.setOption(option, true);} catch (err) {console.error('圖表配置失敗:', err);this.error = '圖表渲染失敗';}},resizeChart() {const chartInstance = this.$options.chartInstance;if (chartInstance) {chartInstance.resize();}},destroyChart() {const chartInstance = this.$options.chartInstance;if (chartInstance) {chartInstance.dispose();this.$options.chartInstance = null;}}}
};
</script><style scoped>
.attendance-chart {width: 100%;height: 350px;padding: 12px;background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);position: relative;
}.loading,
.error,
.no-data {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);text-align: center;color: #666;
}.error {color: #f56c6c;
}.error button {margin-top: 8px;padding: 4px 12px;background: #f56c6c;color: white;border: none;border-radius: 4px;cursor: pointer;
}.no-data {color: #999;
}
</style>

ECharts 在 Vue 中的正確使用方式

關鍵修改點

1. 移除響應式的 chartInstance

  • ? 不再在 data() 中聲明 chartInstance
  • ? 改為使用 this.$options.chartInstance 存儲 ECharts 實例

2. 統一實例訪問方式

  • 所有方法中通過 this.$options.chartInstance 訪問圖表實例
  • 確保不會觸發 Vue 的響應式系統

3. 完善銷毀機制

destroyChart() {const chartInstance = this.$options.chartInstanceif (chartInstance) {chartInstance.dispose()this.$options.chartInstance = null}
}
為什么不能使用響應式變量?
ECharts 實例被 Vue 響應式代理后會導致:
?? ECharts 內部方法調用異常
?? 圖例點擊等交互事件失效
?? 可能引發內存泄漏
?? 性能下降替代方案
// 方案1:使用組件選項
this.$options.chartInstance = echarts.init()// 方案2:在 created 中定義非響應式屬性
created() {this.chartInstance = null
}

注意事項

確保容器存在

mounted() {this.$nextTick(() => {this.fetchData()})
}
處理動態數據更新
watch: {'chartData.attendanceData': {handler() {this.updateChart()},deep: true}
}
添加加載狀態
updateChart() {if (this.$options.chartInstance) {this.$options.chartInstance.showLoading()// ...設置option...this.$options.chartInstance.hideLoading()}
}
最終效果:經過這些修改后,圖表的所有交互功能(包括圖例點擊)都將正常工作。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91047.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91047.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91047.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Django模型開發:模型字段、元數據與繼承全方位講解

文章目錄一、模型字段類型詳解Django 與 MySQL 字段類型映射整數類型深度對比二、常用字段選項null 與 blank 的區別注釋與幫助文本默認值設置日期時間特殊選項選項列表&#xff08;choices&#xff09;三、模型元數據與方法模型 Meta 類模型管理器&#xff08;Manager&#xf…

墨者:SQL注入實戰-MySQL

1. 墨者學院&#xff1a;SQL注入實戰-MySQL&#x1f680; 2. 實訓重點目標? 目標一&#xff1a; 了解sqlmap的使用及其tamper插件的使用&#xff1b; 目標二&#xff1a; 了解base64編碼及解碼。 3. 解題方向&#x1f50d; 目標網站的id參數通過Base64編碼傳輸&#xff0c;…

Milvus 實戰全流程

&#x1f4da; 學習路徑總覽1. Milvus 基礎知識什么是向量數據庫&#xff1f;Milvus 的核心概念&#xff08;collection、field、index、partition、segment&#xff09;Milvus 和 Faiss、Annoy、HNSW 的區別2. 安裝與部署Docker 快速部署 Milvus&#xff08;推薦&#xff09;本…

Mysql數據庫基礎(入門)

目錄 一.認識Sql 1.什么是Sql 2.Sql的作用 3.Sql通用語法 4.Sql分類 二.數據庫的操作&#xff08;DDL&#xff09; 1.創建數據庫 2.顯示/使用數據庫 3.修改數據庫 4.刪除數據庫 三.常用數據類型 1.數值類型 2.字符串類型 3.日期類型 4.詳細的數據類型 四.表的操…

MySQL 鎖機制 15 連問 · 面試速答版

一、腦圖&#xff1a;鎖全景&#xff08;先記結構&#xff0c;再填細節&#xff09; 鎖層級 ├─ 表鎖 │ ├─ 意向鎖 IS / IX │ └─ 表鎖 READ / WRITE └─ 行鎖├─ 記錄鎖 Record├─ 間隙鎖 Gap└─ 臨鍵鎖 Next-Key二、15 問 15 答&#xff08;面試官一問一…

【Linux】發展歷程

很高興為您詳細介紹Linux操作系統的詳細發展歷程。Linux是一個自由和開放源代碼的操作系統內核&#xff0c;由林納斯托瓦茲&#xff08;Linus Torvalds&#xff09;于1991年首次發布。以下是Linux操作系統的主要發展里程碑&#xff1a;1. Linux 0.01 (1991)發布日期&#xff1a…

LNMP架構+wordpress實現動靜分離

WordPress簡稱WP&#xff0c;最初是一款博客系統&#xff0c;后逐步演化成一款免費的CMS&#xff08;內容管理系統/建站系統&#xff09;。 WordPress網站的適用場景&#xff1a; 博客 企業官網 作品集網站 電商平臺 線上教育系統 論壇和社群網站 甚至會員系統、訂閱內容…

智慧燈桿:不止于照明,塔能科技的城市感知網絡野心

當夜幕悄然降臨&#xff0c;城市里的路燈便依次亮了起來&#xff0c;它們可不單單照亮了行人前行的路以及車輛行駛的道路&#xff0c;實際上還在悄無聲息地經歷著一場變革。現如今的路燈&#xff0c;早已不再僅僅充當單純的照明工具這么一個角色了&#xff0c;而是逐漸轉變成了…

【Linux內核模塊】調試技巧

內核模塊開發最讓人頭疼的不是寫代碼&#xff0c;而是調試 —— 代碼編譯通過了&#xff0c;加載后卻要么沒反應&#xff0c;要么直接讓系統崩潰。這就像在黑屋子里修機器&#xff0c;看不見摸不著。其實內核調試有一套成熟的工具箱&#xff0c;掌握這些工具和技巧&#xff0c;…

RK3568筆記九十一:QT環境搭建

若該文為原創文章,轉載請注明原文出處。 記錄按照正點原子給的手冊搭建QT環境 參考《09【正點原子】ATK-DLRK3568_Qt開發環境搭建V1.2.pdf》 一、安裝 1、下載 https://mirrors.sau.edu.cn/qt/archive/online_installers/4.6/qt-unified-linux-x64-4.6.0-online.run 2、賦…

面試實戰,問題十六,Java面試,消息隊列,如何避免消息重復消費,怎么回答

在Java面試中&#xff0c;關于消息隊列如何防止消息被重復消費的問題&#xff0c;可以從以下幾個方面進行回答&#xff0c;結合系統架構設計、消息隊列機制和業務邏輯處理&#xff0c;確保在不同場景下實現消息的冪等性。 1. 消息隊列重復消費的根本原因 消息重復消費的根本原因…

PDF轉圖片實用指南:如何批量高效轉換?

將PDF轉換為圖片后&#xff0c;可以更方便地在演示文稿、網頁或電子相冊中使用這些資料&#xff0c;以便更好地展示信息。它 是一款支持多文件批量轉換的工具&#xff0c;可將多個 PDF 文檔一鍵轉換為圖片格式。雖然界面為英文&#xff0c;但操作簡單&#xff0c;不影響使用。你…

走入Linux的世界:編輯器Vim

嘿&#xff0c;各位技術潮人&#xff01;好久不見甚是想念。生活就像一場奇妙冒險&#xff0c;而編程就是那把超酷的萬能鑰匙。此刻&#xff0c;陽光灑在鍵盤上&#xff0c;靈感在指尖跳躍&#xff0c;讓我們拋開一切束縛&#xff0c;給平淡日子加點料&#xff0c;注入滿滿的pa…

PyTorch中神經網絡的模型構建

要構建自定義模型&#xff0c;需完成兩個核心步驟&#xff1a;繼承 nn.Module 類&#xff1b;重載 __init__ 方法&#xff08;初始化&#xff09;和 forward 方法&#xff08;前向計算&#xff09; 神經網絡的構造 初始化方法&#xff08;__init__&#xff09; def __init__…

QML QtCharts坐標軸系統

QtCharts是Qt框架中強大的數據可視化模塊&#xff0c;它提供了豐富的圖表類型和靈活的坐標軸系統&#xff0c;能夠滿足各種數據展示需求。本文將全面介紹QML中QtCharts的坐標軸系統&#xff0c;包括數值坐標軸(ValueAxis)、對數坐標軸(LogValueAxis)、分類坐標軸(CategoryAxis)…

TI 2025全國電賽猜題

本科組可能的題目方向本科組器材更側重高頻信號處理、復雜控制系統、精密測量及多設備協同&#xff0c;可能涉及以下題目&#xff1a;四旋翼飛行器相關任務題目示例&#xff1a;設計 “基于四旋翼的 UV 光控自主導航系統”任務要求&#xff1a;利用四旋翼飛行器&#xff08;最大…

Python自動化運維實戰指南

什么是自動化運維定義與背景自動化運維是指利用工具和腳本自動執行傳統上需要人工操作的IT運維任務&#xff0c;包括但不限于服務器配置管理、軟件部署、監控告警、日志分析等日常工作。隨著互聯網業務規模的擴大&#xff0c;傳統手工運維方式已無法滿足快速部署、規模化管理等…

k8s的csi對接GPFS

在 Kubernetes&#xff08;k8s&#xff09;集群中&#xff0c;通過 CSI&#xff08;Container Storage Interface&#xff09;對接 GPFS&#xff08;General Parallel File System&#xff0c;現為 IBM Spectrum Scale&#xff09;是實現高性能共享存儲的重要方案。GPFS 作為并…

HTB賽季8靶場 - era

nmap掃描 └─$ nmap -p- --min-rate 1000 -T4 10.129.137.201 -oA nmapfullscan Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-27 21:19 EDT Warning: 10.129.137.201 giving up on port because retransmission cap hit (6). …

Bug貓學習史#1:面向對象

在Java編程中&#xff0c;掌握幾個核心概念對深入學習至關重要&#xff1a;類屬性建議采用包裝類以提升靈活性&#xff1b;建造者模式中this關鍵字能有效簡化對象構建過程&#xff1b;static關鍵字涉及類的加載機制&#xff1b;接口默認使用public修飾符并支持默認方法實現&…