<template>
<div ref="elRef" class="chart-container"></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, onActivated, onDeactivated, nextTick } from 'vue'
import { debounce } from 'lodash-es'
import { useDesign } from '@/hooks/web/useDesign'
import * as echarts from 'echarts' // 明确导入 echarts
const { variables } = useDesign()
// 1. 类型定义(如果使用 TypeScript)
// type ElRef = HTMLElement | null
const elRef = ref(null)
const contentEl = ref(null)
let chartInstance = null
// 2. 创建防抖函数
const debouncedResize = debounce(() => {
if (chartInstance) {
chartInstance.resize()
}
}, 100)
// 3. 内容区域变化处理器
const handleContentResize = (e) => {
if (e.propertyName === 'width' || e.propertyName === 'height') {
debouncedResize()
}
}
// 4. 初始化图表
const initChart = async () => {
await nextTick() // 确保 DOM 已渲染
if (!elRef.value) return
// 销毁现有实例(如果存在)
if (chartInstance) {
chartInstance.dispose()
}
try {
chartInstance = echarts.init(elRef.value)
// 5. 定义图表配置
const option = {
// ... 你的图表配置
// 示例配置
title: { text: '示例图表' },
tooltip: {},
xAxis: { data: ['A', 'B', 'C'] },
yAxis: {},
series: [{ type: 'bar', data: [5, 20, 36] }]
}
chartInstance.setOption(option)
// 6. 初始 resize(处理 SSR 或延迟加载)
debouncedResize()
} catch (error) {
console.error('图表初始化失败:', error)
}
}
// 7. 清理函数
const disposeChart = () => {
if (chartInstance) {
chartInstance.dispose()
chartInstance = null
}
}
// 8. 事件监听器管理
const addEventListeners = () => {
window.addEventListener('resize', debouncedResize)
const contentElement = document.querySelector(`.${variables.namespace}-layout-content`)
if (contentElement) {
contentEl.value = contentElement
contentElement.addEventListener('transitionend', handleContentResize)
// 也监听 animationend,因为某些动画可能使用 animation
contentElement.addEventListener('animationend', handleContentResize)
}
}
const removeEventListeners = () => {
window.removeEventListener('resize', debouncedResize)
if (contentEl.value) {
contentEl.value.removeEventListener('transitionend', handleContentResize)
contentEl.value.removeEventListener('animationend', handleContentResize)
}
}
// 9. 生命周期钩子
onMounted(() => {
initChart()
addEventListeners()
})
onBeforeUnmount(() => {
removeEventListeners()
disposeChart()
})
// 10. keep-alive 支持
onActivated(() => {
if (chartInstance) {
// 延迟执行,确保组件完全激活
nextTick(() => {
chartInstance.resize()
})
}
})
onDeactivated(() => {
// 可选:在组件失活时暂停图表(节省资源)
// if (chartInstance) {
// chartInstance.clear()
// }
})
// 11. 提供外部 API(可选)
defineExpose({
refresh: () => {
disposeChart()
initChart()
},
getChart: () => chartInstance,
resize: () => {
if (chartInstance) {
chartInstance.resize()
}
}
})
</script>
<style scoped>
.chart-container {
width: 100%;
height: 100%; /* 或使用 CSS 变量 */
min-height: 400px; /* 设置最小高度 */
}
</style>
echarts图图表屏幕变化自适应
于 2025-07-31 11:00:30 首次发布