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}`);
...
}
相关推荐
linux_cfan1 小时前
2026版 WordPress 视频插件终极选型:知识付费创作者如何低成本打造专业在线课堂?
前端·javascript·音视频·html5
pas1361 小时前
46-mini-vue 实现编译 template 为 render 函数
前端·javascript·vue.js
YuMiao2 小时前
把 WebSocket 服务迁移到 Cloudflare Durable Objects —— 以一次协同编辑实战为例
javascript·node.js
Highcharts.js3 小时前
Highcharts跨域数据加载完全指南:JSONP原理与实战
javascript·数据库·开发文档·highcharts·图表开发·跨域数据
skywalk81633 小时前
electrobun 使用TypeScript构建超快速、小巧且跨平台的桌面应用程序(待续)
前端·javascript·typescript
薛一半5 小时前
React的数据绑定
前端·javascript·react.js
爱看书的小沐5 小时前
【小沐杂货铺】基于Three.js渲染三维无人机Drone(WebGL / vue / react )
javascript·vue.js·react.js·无人机·webgl·three.js·drone
ShenJLLL12 小时前
vue部分知识点.
前端·javascript·vue.js·前端框架
Never_Satisfied19 小时前
在JavaScript / HTML中,数组查找第一个符合要求元素
开发语言·javascript·html
HelloReader20 小时前
Tauri 2 创建项目全流程create-tauri-app 一键脚手架 + Tauri CLI 手动接入
前端·javascript·vue.js