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}`);
...
}
相关推荐
EnoYao5 小时前
我写了一个团队体检报告 Skill,把摸鱼的同事扒出来了😅
前端·javascript
Never_Satisfied5 小时前
在JavaScript / Node.js中,package.json文件中的依赖项自动选择最新版安装
javascript·node.js·json
蓝莓味的口香糖5 小时前
【vue3】组件的批量全局注册
前端·javascript·vue.js
Fighting_p7 小时前
【element UI】el-select 组件下拉数据某一行文字过多时,文字换行展示,避免el-select下拉框被撑宽,导致页面过丑
前端·javascript
未来之窗软件服务7 小时前
幽冥大陆(一百12)js打造json硬件管道——东方仙盟筑基期
开发语言·javascript·算法·json·仙盟创梦ide·东方仙盟·东方仙盟算法
王家视频教程图书馆7 小时前
vue3从本地选择一个视频 展示到视频组件中
前端·javascript·音视频
天外来鹿8 小时前
Map/Set/WeakMap/WeakSet学习笔记
前端·javascript·笔记·学习
紫_龙8 小时前
最新版vue3+TypeScript开发入门到实战教程之vue3与vue2语法优劣对比
前端·javascript·typescript
全栈小59 小时前
【前端】Vue 组件开发中的枚举值验证:从一个Type属性错误说起
前端·javascript·vue.js
Joker Zxc9 小时前
【前端基础(Javascript部分)】4、JavaScript的分支语句
开发语言·前端·javascript