数据大屏怎样做多分辨率适配?图表组件如何封装和避免内存泄漏?

先理解原理和示例,再练习完整口述与追问。

大屏通常按设计稿尺寸(如 1920×1080)开发,再用 transform scale 等比缩放,保持比例并处理留白;也可用 vw/vh 或 rem 方案。图表监听容器尺寸用 ResizeObserver,组件卸载时调用 chart.dispose()。实时数据更新用 setOption 增量合并,控制刷新频率和数据点数量,长时间运行需关注内存。

scale 方案简单且还原度高,缺点是比例不同时会出现黑边,文字缩小后可能模糊,鼠标坐标也受缩放影响(部分图表库需要额外处理)。vw/vh 方案能铺满屏幕,但宽高比差异大时元素会变形。ECharts 实例绑定在 DOM 上,组件卸载不调用 dispose,实例和事件监听都会残留。

在 Vue 中,图表实例不要放进 ref 或 reactive,深层代理会带来大量开销甚至报错,使用 shallowRef 或普通变量;监听窗口大小用 ResizeObserver 观察容器,能覆盖侧边栏折叠等非窗口变化的场景,并做节流。数据推送频繁时,合并为每秒一次更新,滚动窗口只保留最近 N 个点。

js
import { onMounted, onBeforeUnmount, shallowRef, watch } from 'vue'
import * as echarts from 'echarts'

export function useChart(elRef, optionRef) {
  const chart = shallowRef(null)
  let observer
  onMounted(() => {
    chart.value = echarts.init(elRef.value)
    chart.value.setOption(optionRef.value)
    observer = new ResizeObserver(() => chart.value?.resize())
    observer.observe(elRef.value)
  })
  watch(optionRef, option => chart.value?.setOption(option), { deep: true })
  onBeforeUnmount(() => {
    observer?.disconnect()
    chart.value?.dispose()
    chart.value = null
  })
  return chart
}

大屏 7×24 小时运行,定时器、WebSocket 重连与图表实例的泄漏会累积成崩溃,要用内存快照验证;setOption 的 notMerge 用错会导致旧系列残留或动画闪烁。

大屏我一般按设计稿尺寸开发,再根据视口算出比例用 transform scale 缩放并居中,牺牲一点留白保证还原度;需要铺满时用 vw、vh。图表封装成组合式函数:初始化后用 ResizeObserver 监听容器尺寸,数据变化时 setOption,卸载时断开观察并 dispose;Vue 中实例用 shallowRef 避免深层代理。实时数据要合并刷新、限制数据点,长时间运行要用内存快照检查泄漏。