Element Plus El-Row和El-Col布局:解决中型屏幕下图表组件高度溢出问题
在使用Element Plus的El-Row和El-Col栅格系统开发响应式页面时,常常会遇到图表组件在不同屏幕尺寸下表现不一致的问题,其中中型屏幕(通常是768px到1200px区间)下图表高度溢出容器是比较典型的场景。本文将分析原因并提供可行的解决方案。
问题场景说明
假设我们有一个数据看板页面,使用El-Row和El-Col实现两列布局,左侧放置筛选条件,右侧放置图表组件。在桌面端大屏幕下布局正常,但在中型屏幕(比如平板设备)下,右侧图表容器的高度超过了El-Col的设定高度,导致图表内容溢出,甚至出现页面滚动异常的问题。
基础的布局代码如下:
<template>
<el-row :gutter="20">
<el-col :span="8" :md="8" :sm="24">
<div class="filter-container">
<!-- 筛选条件内容 -->
</div>
</el-col>
<el-col :span="16" :md="16" :sm="24">
<div class="chart-container">
<div ref="chartRef" class="chart"></div>
</div>
</el-col>
</el-row>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
const chartRef = ref(null)
let chartInstance = null
onMounted(() => {
chartInstance = echarts.init(chartRef.value)
chartInstance.setOption({
// 图表配置项
xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'] },
yAxis: { type: 'value' },
series: [{ data: [120, 200, 150, 80, 70], type: 'bar' }]
})
})
onUnmounted(() => {
chartInstance?.dispose()
})
</script>
<style scoped>
.filter-container {
height: 400px;
background-color: #f5f5f5;
padding: 20px;
}
.chart-container {
height: 400px;
background-color: #f0f0f0;
}
.chart {
width: 100%;
height: 100%;
}
</style>在上述代码中,我们给图表容器和筛选容器都设定了固定的400px高度,在大屏幕下没有问题,但在中型屏幕下,由于El-Col的栅格计算可能存在边距、内边距兼容问题,或者图表初始化时容器尺寸还没有完全计算完成,就会出现高度溢出的问题。
问题原因分析
固定高度适配性差:使用固定像素高度,无法跟随屏幕尺寸变化自动调整,中型屏幕下容器高度和图表高度不匹配。
栅格系统间隙影响:
El-Row的gutter属性会在El-Col上添加左右内边距,中型屏幕下栅格计算可能出现偏差,导致容器实际高度超出预期。图表初始化时机问题:如果在容器尺寸还没有完全计算完成时就初始化图表,图表的渲染高度会基于错误的容器尺寸,导致后续溢出。
响应式断点适配缺失:没有针对中型屏幕的
:md断点做额外的高度规则配置,导致布局规则和大屏幕一致,无法适配中等尺寸。
解决方案
方案一:使用响应式高度计算
放弃固定像素高度,改用相对单位或者基于父容器动态计算高度,结合Vue的响应式特性适配不同屏幕。
修改代码如下:
<template>
<el-row :gutter="20" class="dashboard-row">
<el-col :span="8" :md="8" :sm="24" class="filter-col">
<div class="filter-container">
<!-- 筛选条件内容 -->
</div>
</el-col>
<el-col :span="16" :md="16" :sm="24" class="chart-col">
<div class="chart-container" ref="containerRef">
<div ref="chartRef" class="chart"></div>
</div>
</el-col>
</el-row>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
import * as echarts from 'echarts'
import { useResizeObserver } from '@vueuse/core'
const chartRef = ref(null)
const containerRef = ref(null)
let chartInstance = null
// 初始化图表
const initChart = () => {
if (!chartRef.value) return
chartInstance = echarts.init(chartRef.value)
chartInstance.setOption({
xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'] },
yAxis: { type: 'value' },
series: [{ data: [120, 200, 150, 80, 70], type: 'bar' }]
})
}
// 监听容器尺寸变化,重新计算图表大小
useResizeObserver(containerRef, () => {
chartInstance?.resize()
})
onMounted(() => {
nextTick(() => {
initChart()
})
})
onUnmounted(() => {
chartInstance?.dispose()
})
</script>
<style scoped>
.dashboard-row {
height: calc(100vh - 120px); /* 基于视口高度动态计算,减去头部和底部高度 */
}
.filter-col {
height: 100%;
}
.chart-col {
height: 100%;
}
.filter-container {
height: 100%;
background-color: #f5f5f5;
padding: 20px;
box-sizing: border-box; /* 确保内边距不会增加容器总高度 */
}
.chart-container {
height: 100%;
background-color: #f0f0f0;
box-sizing: border-box;
}
.chart {
width: 100%;
height: 100%;
}
</style>该方案通过calc(100vh - 120px)动态计算行容器高度,同时给添加box-sizing: border-box,避免内边距导致高度溢出,配合useResizeObserver监听容器尺寸变化,实时调整图表大小。
方案二:针对中型屏幕自定义断点样式
如果项目中需要更精细的响应式控制,可以通过媒体查询针对中型屏幕单独设置高度规则。
在样式中添加如下代码:
/* 中型屏幕适配,768px到1200px区间 */
@media screen and (min-width: 768px) and (max-width: 1200px) {
.dashboard-row {
height: calc(100vh - 100px);
}
.filter-container {
height: 350px;
}
.chart-container {
height: 350px;
}
}该方案可以在中型屏幕下主动调整容器高度,避免默认的400px高度在小尺寸屏幕下出现溢出,同时可以和方案一结合使用,提升适配的灵活性。
方案三:优化图表初始化时机
如果问题是因为初始化时容器尺寸未计算完成导致的,可以使用nextTick结合setTimeout延迟初始化,或者监听栅格布局完成事件后再初始化图表。
修改初始化逻辑如下:
onMounted(() => {
// 延迟初始化,确保容器尺寸已经计算完成
setTimeout(() => {
nextTick(() => {
initChart()
})
}, 100)
})这种方式可以规避因DOM渲染未完成导致的容器尺寸计算错误问题,适合对初始化时机要求较高的场景。
方案对比与推荐
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 响应式高度计算 | 适配性最好,覆盖所有屏幕尺寸,无需单独维护断点规则 | 需要引入额外的响应式监听逻辑,依赖@vueuse/core等工具库 | 所有需要响应式布局的图表页面 |
| 自定义断点样式 | 实现简单,无需修改逻辑代码,只需调整样式 | 需要单独维护不同断点的样式规则,扩展性一般 | 仅需要适配少数固定断点的场景 |
| 优化初始化时机 | 改动小,仅调整初始化逻辑 | 无法解决根本性尺寸适配问题,只能规避初始化阶段的异常 | 初始化阶段出现溢出的临时解决场景 |
实际开发中推荐优先使用方案一,结合方案二的断点样式做补充,可以最大化解决中型屏幕下图表组件高度溢出的问题,同时保证布局在所有屏幕尺寸下的稳定性。