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}`);
...
}
相关推荐
她说可以呀8 小时前
Vue插槽
前端·javascript·vue.js
qq_448011168 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
FRing0311 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
兰亭妙微UI设计公司13 小时前
兰亭妙微ui设计公司分享:B端组件命名如何支持团队协作
前端·javascript·vue.js
小大宇14 小时前
Vue知识点-ElementPlus-03提示框+询问+通知
前端·javascript·vue.js
前端技术官15 小时前
前端的技术判断力是怎么练出来的?
javascript·web前端·localstorage·debounce·弱网处理
程序员大阳16 小时前
副队长JavaScript教程(60)-BOM 初识:window 对象与浏览器模型
javascript·bom·window对象·浏览器模型
web打印社区16 小时前
Chrome-kiosk-printing能上生产吗
开发语言·前端·javascript·chrome·websocket
志尊宝17 小时前
AI原生前端开发(041):AI辅助的状态管理(Zustand/Pinia)
前端·javascript·ai-native
Geoffwo17 小时前
DSH-SKILL基础
javascript