import { ref, onMounted, onBeforeUnmount, watch } from 'vue'; import * as echarts from 'echarts'; import { useResizeObserver } from '@vueuse/core'; /** * ECharts Hook * @param containerRef 图表容器 Ref * @param options 图表配置 Ref * @param theme 主题配置(可选) * @param autoResize 是否自动响应容器大小变化(默认 true) */ export function useECharts( containerRef, options, theme = 'macarons', autoResize = true ) { const chartInstance = ref(null); const resizeObserver = ref(null); let eventQueue = [] // 初始化图表 const init = () => { if (!containerRef.value) return; dispose(); chartInstance.value = markRaw(echarts.init(containerRef.value, theme)) chartInstance.value.setOption(options.value); eventQueue = eventQueue.filter((handler) => { handler() return false }) // 初始化 resize 监听 if (autoResize) { setupResizeObserver(); } }; // 设置 resize 监听 const setupResizeObserver = () => { if (!containerRef.value) return; resizeObserver.value = useResizeObserver(containerRef.value, () => { resize(); }); }; // 销毁图表 const dispose = () => { // 移除 resize 监听 if (resizeObserver.value) { resizeObserver.value.stop(); resizeObserver.value = null; } // 销毁图表实例 if (chartInstance.value && !chartInstance.value.isDisposed()) { chartInstance.value.dispose(); chartInstance.value = null; } }; // 重置图表 const reset = () => { dispose(); init(); }; // 手动触发 resize const resize = () => { if (chartInstance.value) { try { chartInstance.value.resize(); } catch (error) { console.error('ECharts resize 失败:', error); } } }; const bindEvent = (eventName, callback) => { eventQueue.push(() => chartInstance.value.getZr().on(eventName, callback)) return result } // 监听 options 变化 watch(options, (newOptions) => { if (chartInstance.value) { chartInstance.value.setOption(newOptions); } }, { deep: true, immediate: true }); // 组件生命周期 onMounted(() => { init() }); onBeforeUnmount(() => dispose()); const result = { instance: chartInstance, init, dispose, reset, resize, bindEvent }; return result }