在Vue3中使?echarts?圖表寬度自適應(yīng)變化的操作方法
需求:
有現(xiàn)在這樣一段使用 echarts 的 vue3 代碼:
<template>
<div ref="chartRef" style="width: 600px; height: 400px;"></div>
</template>
<script setup>
import {getCurrentInstance, onMounted, onUnmounted, ref} from 'vue';
const chartRef = ref(null);
let chartInstance = null;
// 通過(guò) getCurrentInstance 訪問(wèn)全局屬性
const {proxy} = getCurrentInstance();
onMounted(() => {
chartInstance = proxy.$echarts.init(chartRef.value);
chartInstance.setOption({
title: {text: '柱狀圖示例'},
tooltip: {},
xAxis: {data: ['A', 'B', 'C', 'D', 'E']},
yAxis: {},
series: [{type: 'bar', data: [10, 20, 30, 40, 50]}]
});
});
onUnmounted(() => {
chartInstance?.dispose(); // 銷毀實(shí)例
});
</script>作用是在界面顯示一個(gè)柱狀圖:

問(wèn)題是在頁(yè)面縮放時(shí),圖表大小始終固定:

希望圖表能夠根據(jù)頁(yè)面寬度自動(dòng)調(diào)整,特別是在頁(yè)面縮放時(shí)。
解決:
在代碼中,chartRef的div被固定設(shè)置為600px寬和400px高,現(xiàn)在需要修改這部分,讓圖表始終占據(jù)頁(yè)面的寬度,并能夠響應(yīng)窗口大小的變化。
為實(shí)現(xiàn)自適應(yīng)寬度。通??梢酝ㄟ^(guò)CSS來(lái)設(shè)置容器的寬度為100%,這樣它會(huì)填充父容器的寬度。
但僅僅設(shè)置CSS可能不夠,因?yàn)镋Charts實(shí)例在初始化后不會(huì)自動(dòng)調(diào)整大小,除非顯式調(diào)用圖表實(shí)例的 resize 方法。
所以,解決方案的大致步驟應(yīng)該是:
- 修改模板中的div樣式,將寬度設(shè)置為100%,這樣它會(huì)根據(jù)父容器自適應(yīng)。
- 在Vue組件中添加一個(gè)監(jiān)聽(tīng)窗口大小變化的事件,當(dāng)窗口resize時(shí),觸發(fā)ECharts實(shí)例的resize方法。
- 確保在組件卸載時(shí)移除事件監(jiān)聽(tīng),避免內(nèi)存泄漏。
代碼:
<template>
<!-- 外層容器用于控制圖表寬度,高度可根據(jù)需求調(diào)整 -->
<div class="chart-container">
<div ref="chartRef" class="chart"></div>
</div>
</template>
<script setup>
import { getCurrentInstance, onMounted, onUnmounted, ref } from 'vue';
const chartRef = ref(null);
let chartInstance = null;
const { proxy } = getCurrentInstance();
// 處理窗口縮放
const handleResize = () => {
if (chartInstance) {
// 添加防抖優(yōu)化性能(可選)
chartInstance.resize();
}
};
onMounted(() => {
// 初始化圖表
chartInstance = proxy.$echarts.init(chartRef.value);
chartInstance.setOption({
title: { text: '響應(yīng)式柱狀圖' },
tooltip: {},
xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
yAxis: {},
series: [{ type: 'bar', data: [10, 20, 30, 40, 50] }]
});
// 監(jiān)聽(tīng)窗口變化
window.addEventListener('resize', handleResize);
// 初始執(zhí)行一次確保尺寸正確
setTimeout(handleResize, 0);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
</script>
<style scoped>
.chart-container {
width: 100%;
padding: 20px; /* 可根據(jù)需求調(diào)整 */
}
.chart {
width: 100%;
height: 200px; /* 固定高度,可改為 min-height 或使用 calc 動(dòng)態(tài)計(jì)算 */
/* 可選:添加最大寬度限制 */
max-width: 1200px;
margin: 0 auto;
}
/* 移動(dòng)端適配 */
@media (max-width: 768px) {
.chart {
height: 300px;
}
}
</style>效果如下:

主要修改點(diǎn)說(shuō)明:
1,容器結(jié)構(gòu)優(yōu)化:
- 添加外層容器 .chart-container 控制布局
- 圖表元素使用百分比寬度 width: 100%
2,響應(yīng)式處理:
window.addEventListener('resize', handleResize);監(jiān)聽(tīng)窗口縮放事件,觸發(fā)圖表 resize 方法
3,自動(dòng)調(diào)整邏輯:
const handleResize = () => {
chartInstance?.resize();
};調(diào)用 ECharts 實(shí)例的 resize() 方法自適應(yīng)容器
4,CSS 增強(qiáng):
- 添加響應(yīng)式高度(通過(guò)媒體查詢)
- 限制最大寬度避免過(guò)寬
- 添加安全間距(padding/margin)
如果需要高度也自適應(yīng),可以:
// 在 handleResize 中動(dòng)態(tài)計(jì)算高度
const containerWidth = chartRef.value.offsetWidth;
const aspectRatio = 9 / 16; // 16:9 比例
chartRef.value.style.height = `${containerWidth * aspectRatio}px`;
chartInstance.resize();響應(yīng)式斷點(diǎn):
/* 在樣式中添加更多斷點(diǎn) */
@media (max-width: 480px) {
.chart {
height: 250px;
}
}父容器控制:確保外層父元素有正確的布局設(shè)置
/* 在父組件中 */
.parent-container {
width: 100%;
display: flex;
justify-content: center;
}擴(kuò)展:
1,防抖處理
是否需要考慮防抖處理,避免頻繁觸發(fā)resize導(dǎo)致性能問(wèn)題。但ECharts的resize方法本身有一定的優(yōu)化,可能不需要額外處理,但根據(jù)具體情況可以添加。
// 防抖版 resize(在 handleResize 頂部添加)
let resizeTimer;
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
chartInstance.resize();
}, 200);2,多圖表并列縮放問(wèn)題
以兩個(gè)圖表并排并考慮縮放為例,這涉及到布局和響應(yīng)式處理兩個(gè)方面。
布局方面,我需要考慮使用CSS Flexbox或者Grid來(lái)實(shí)現(xiàn)并排。
響應(yīng)式方面,需要確保每個(gè)圖表都能在窗口大小變化時(shí)正確調(diào)整尺寸,并且可能需要在移動(dòng)設(shè)備上切換為垂直排列。
接下來(lái),我需要回憶ECharts的resize方法是否正確應(yīng)用,是否需要為每個(gè)圖表實(shí)例單獨(dú)調(diào)用resize。需要確保每個(gè)圖表容器都有正確的寬度設(shè)置,比如各占50%或者使用Flexbox的自動(dòng)調(diào)整。
<template>
<!-- 使用 Flex 布局容器 -->
<div class="charts-container">
<!-- 單個(gè)圖表容器 -->
<div class="chart-wrapper">
<div ref="chartRef1" class="chart"></div>
</div>
<!-- 第二個(gè)圖表容器 -->
<div class="chart-wrapper">
<div ref="chartRef2" class="chart"></div>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance, onMounted, onUnmounted, ref } from 'vue';
const chartRef1 = ref(null);
const chartRef2 = ref(null);
let chartInstance1 = null;
let chartInstance2 = null;
const { proxy } = getCurrentInstance();
// 公共配置項(xiàng)
const baseOption = {
tooltip: {},
xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
yAxis: {},
};
// 初始化圖表
const initChart = (ref, option) => {
const chart = proxy.$echarts.init(ref.value);
chart.setOption(option);
return chart;
};
// 帶防抖的 resize 處理
let resizeTimer;
const handleResize = () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
chartInstance1?.resize();
chartInstance2?.resize();
}, 200);
};
onMounted(() => {
// 初始化兩個(gè)圖表
chartInstance1 = initChart(chartRef1, {
...baseOption,
title: { text: '圖表1' },
series: [{ type: 'bar', data: [10, 20, 30, 40, 50] }]
});
chartInstance2 = initChart(chartRef2, {
...baseOption,
title: { text: '圖表2' },
series: [{ type: 'bar', data: [50, 40, 30, 20, 10] }]
});
// 監(jiān)聽(tīng)窗口變化
window.addEventListener('resize', handleResize);
// 初始調(diào)整
handleResize();
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
chartInstance1?.dispose();
chartInstance2?.dispose();
});
</script>
<style scoped>
/* 主容器:Flex 布局 */
.charts-container {
display: flex;
gap: 20px; /* 圖表間距 */
width: 100%;
padding: 20px;
box-sizing: border-box;
}
/* 單個(gè)圖表容器 */
.chart-wrapper {
flex: 1; /* 平分剩余空間 */
min-width: 0; /* 解決 flex 容器溢出問(wèn)題 */
}
.chart {
width: 100%;
height: 400px; /* 統(tǒng)一高度 */
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}
/* 移動(dòng)端響應(yīng)式 */
@media (max-width: 768px) {
.charts-container {
flex-direction: column; /* 垂直排列 */
}
.chart {
height: 300px;
}
}
</style>效果如下:

1,布局方案:
使用 display: flex 創(chuàng)建彈性容器gap: 20px 設(shè)置圖表間距flex: 1 使兩個(gè)圖表容器平分可用空間min-width: 0 修復(fù) flex 容器溢出問(wèn)題
2,響應(yīng)式控制:
媒體查詢 @media (max-width: 768px) 實(shí)現(xiàn)移動(dòng)端垂直布局統(tǒng)一高度設(shè)置保證視覺(jué)一致性容器寬度始終為 100% 適配父元素
3,圖表控制:
封裝 initChart 方法復(fù)用初始化邏輯使用防抖函數(shù)優(yōu)化頻繁 resize 性能同時(shí)處理兩個(gè)圖表的 resize 事件
4,樣式增強(qiáng):
添加陰影和圓角提升視覺(jué)效果設(shè)置 box-sizing: border-box 避免布局錯(cuò)位背景色設(shè)置保證圖表可見(jiàn)性
到此這篇關(guān)于在Vue 3中使 echarts 圖表寬度自適應(yīng)變化的文章就介紹到這了,更多相關(guān)Vue echarts 圖表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue2.0中自適應(yīng)echarts圖表、全屏插件screenfull的使用
- vue3集成echarts數(shù)據(jù)刷新后圖表不刷新的解決方法
- vue之使用echarts圖表setOption多次很卡問(wèn)題及解決
- Vue動(dòng)態(tài)加載ECharts圖表數(shù)據(jù)的方式
- vue中實(shí)現(xiàn)當(dāng)前時(shí)間echarts圖表時(shí)間軸動(dòng)態(tài)的數(shù)據(jù)(實(shí)例代碼)
- vue中Echarts圖表寬度沒(méi)占滿的問(wèn)題
- vue項(xiàng)目中vue-echarts講解及常用圖表實(shí)現(xiàn)方案(推薦)
- Vue中使用Echarts可視化圖表寬度自適應(yīng)的完美解決方案
- Vue Element前端應(yīng)用開(kāi)發(fā)之echarts圖表
- vue使用echarts圖表自適應(yīng)的幾種解決方案
相關(guān)文章
在Vue3中實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù)的代碼示例
Vue3作為目前最熱門的前端框架之一,以其輕量化、易用性及性能優(yōu)勢(shì)吸引了大量開(kāi)發(fā)者,在開(kāi)發(fā)過(guò)程中,不可避免地需要在組件之間傳遞數(shù)據(jù),本文將詳細(xì)講解在Vue3中如何實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù),并通過(guò)具體示例代碼使概念更加清晰2024-07-07
解決Vue + Echarts 使用markLine標(biāo)線(precision精度問(wèn)題)
這篇文章主要介紹了解決Vue + Echarts 使用markLine標(biāo)線(precision精度問(wèn)題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
Vue項(xiàng)目總結(jié)之webpack常規(guī)打包優(yōu)化方案
這篇文章主要介紹了vue項(xiàng)目總結(jié)之webpack常規(guī)打包優(yōu)化方案,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
Element-ui Image圖片按需引入大圖預(yù)覽
這篇文章主要為大家介紹了Element-ui Image圖片按需引入大圖預(yù)覽實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
vue3(optionApi)使用Element Plus庫(kù)沒(méi)有效果的解決方式
這篇文章主要介紹了vue3(optionApi)使用Element Plus庫(kù)沒(méi)有效果的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
nuxt.js添加環(huán)境變量,區(qū)分項(xiàng)目打包環(huán)境操作
這篇文章主要介紹了nuxt.js添加環(huán)境變量,區(qū)分項(xiàng)目打包環(huán)境操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Vue實(shí)現(xiàn)根據(jù)hash高亮選項(xiàng)卡
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)根據(jù)hash高亮選項(xiàng)卡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
完美解決element-ui的el-input設(shè)置number類型后的相關(guān)問(wèn)題
這篇文章主要介紹了完美解決element-ui的el-input設(shè)置number類型后的相關(guān)問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
vue實(shí)現(xiàn)圖書(shū)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)圖書(shū)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12

