uniapp项目中使用echarts

因为多处使用,所以我这里直接采用封装组件的方式。

myChart.vue

csharp 复制代码
<template>
	<view class="chart-container">
		<view class="my-echarts-container" :id="echartsId" :style="{ width: width, height: height }" ref="echartsRef"></view>
	</view>
</template>

<script setup lang="ts">
	import { ref, onMounted, onUnmounted, watch, nextTick, computed } from 'vue';
	import * as echarts from 'echarts';
	import type { ECharts, EChartsOption, EChartsResponsiveOption } from 'echarts';

	const props = defineProps({
		chartOptions: {
			type: Object as () => EChartsOption | EChartsResponsiveOption,
			required: true,
			default: () => ({})
		},
		width: {
			type: String,
			default: '100%'
		},
		height: {
			type: String,
			default: '600rpx'
		}
	});

	const echartsId = computed(() => `my-echarts-${Date.now()}-${Math.floor(Math.random() * 1000)}`);
	const echartsRef = ref<HTMLElement | null>(null);
	let myEcharts : ECharts | null = null;

	// 3. 初始化 ECharts 实例
	const initEcharts = () => {
		// document.querySelector 获取原生 DOM 元素,避免原来的 ref方式报错找不到dom
		  let container: HTMLElement | null = document.querySelector(`#${echartsId.value}`);
		  
		  // 如果 querySelector 获取失败,再使用 ref
		  if (!container && echartsRef.value) {
		    container = echartsRef.value as unknown as HTMLElement;
		  }
		
		  // 判断容器是否有效
		  if (!container) {
		    console.error('ECharts 容器获取失败!无法初始化图表');
		    return;
		  }
		
		  // 销毁已有实例,避免内存泄漏
		  if (myEcharts) {
		    myEcharts.dispose();
		    myEcharts = null;
		  }
		
		  // 原生 ECharts 初始化
		  try {
		    myEcharts = echarts.init(container);
		    renderEcharts();
		    console.log('ECharts 初始化成功!');
		  } catch (err) {
		    console.error('ECharts 初始化失败:', err);
		  }
	};

	// 渲染
	const renderEcharts = () => {
		if (!myEcharts || !props.chartOptions) return;
		try {
			myEcharts.setOption(props.chartOptions, true);
		} catch (err) {
			console.error('ECharts 渲染配置失败:', err);
		}
	};

	// 挂载
	onMounted(() => {
		// 双重 nextTick 确保 DOM 完全渲染(解决部分场景下 DOM 未加载完成问题)
		nextTick(() => {
			nextTick(() => {
				initEcharts();
			});
		});
	});

	// 卸载时销毁实例和事件监听
	onUnmounted(() => {
		if (myEcharts) {
			myEcharts.dispose();
			myEcharts = null;
		}
	});

	// 监听 Props 变化,更新图表
	watch(
		() => props.chartOptions,
		() => {
			nextTick(renderEcharts);
		},
		{ deep: true, immediate: false }
	);

	watch(
		() => [props.width, props.height],
		() => {
			nextTick(initEcharts);
		},
		{ deep: true }
	);

	defineExpose({
		/** 主动更新图表 */
		refresh: renderEcharts,
		getEchartsInstance: () => myEcharts
	});
</script>

<style lang="scss" scoped>
	.my-echarts-container {
	  box-sizing: border-box;
	  visibility: visible;
	  overflow: hidden;
	  background-color: #fafafa;
	  /* 给容器一个最小宽高,避免 UniApp 渲染时宽高丢失 */
	  min-width: 300px;
	  min-height: 400px;
	}
</style>

组件使用:

csharp 复制代码
 <myChart class="m-line" :chartOptions="applyChartOptions" />
...
import type { EChartsOption } from 'echarts';
import myChart from '@/components/myChart/myChart'
...
applyChartOptions.value =  ref<EChartsOption>({...})

uniapp使用echarts常见报错

1、Uncaught (in promise) TypeError: this.dom.getContext is not a function

没有获取到DOM;

排除1:在初始化前检查是否检查DOM有效;

csharp 复制代码
 if (!echartsRef.value) {
    console.error('ECharts 容器 DOM 不存在!');
    return;
  }

排除2:如果是小程序环境,需要做一下兼容处理,使用 uni-ec-canvas 适配;

2、ECharts 容器不是有效的

排除1:优先使用view标签,UniApp H5 端会自动将 编译为
,ref 获取到的元素更稳定

csharp 复制代码
<view class="my-echarts-container" id="my-echarts" :style="{ width: width, height: height }" ref="echartsRef"></view>

排除2:容器获取方式优先使用document.querySelector ,避免 UniApp 对 ref 元素的包装。

csharp 复制代码
let container: HTMLElement | null = document.querySelector(`#my-echarts`);
// 如果 querySelector 获取失败,再使用 ref
		  if (!container && echartsRef.value) {
		    container = echartsRef.value as unknown as HTMLElement;
		  }
		
		  // 判断容器是否有效
		  if (!container) {
		    console.error('ECharts 容器获取失败!无法初始化图表');
		    return;
		  }

排除3:单个页面中多处使用图标组件,应该给容器添加唯一ID

csharp 复制代码
<view class="my-echarts-container" :id="echartsId" :style="{ width: width, height: height }" ref="echartsRef"></view>
csharp 复制代码
const echartsId = computed(() => `my-echarts-${Date.now()}-${Math.floor(Math.random() * 1000)}`);

...
const initEcharts = () => {
...
	let container: HTMLElement | null = document.querySelector(`#${echartsId.value}`);
...
}
相关推荐
Mr.mjw12 分钟前
vue中封装一个环形进度条组件,根据外部盒子大小自适应变化
前端·javascript·vue.js
无心使然14 分钟前
Openlayers调用ArcGis影像服务之一动态地图、地图切片(/exportImage)
前端·javascript·数据可视化
像我这样帅的人丶你还1 小时前
前端监控体系与实践(二):全局监控
前端·javascript·vue.js
顾随1 小时前
(二)kettle--输入与输出
javascript·数据库·kettle
FlyWIHTSKY2 小时前
Vue 3 中 RouteRecord 详解(Vue Router 4)
前端·javascript·vue.js
老王以为2 小时前
前端视角下的 Java
java·javascript·程序员
Alice-YUE2 小时前
【JS高频八股】什么是闭包?
开发语言·javascript·笔记·学习
D_C_tyu2 小时前
JavaScript | 数独游戏核心算法实现
javascript·算法·游戏
海天鹰2 小时前
EXIF-JS
javascript
清汤饺子3 小时前
【译】我的 AI 进阶之路:从怀疑到深度整合
前端·javascript·后端