主要解决思路:
获取图表节点的父级节点宽度然后赋值给图表节点,父级节点可设置成自适应宽度,然后再modal渲染图标一定要注意节点渲染顺序,最后通过浏览器窗口的resize()事件与echarts的resize()方法来结合控制图表大小
以UI框架iview为例,element同理,当我们在使用echarts图表时很多情况下宽度都不是固定,这时我们可能会想到用百分比来解决,然后实际并没用,比如我们设置宽度100%,让他随父级元素自适应大小,结果宽度却直接变成了100px,所以直接设置百分比是没有效果的,这时我们可以使用
this.$refs["myChart"].parentNode.offsetWidth//获取父DOM节点的宽度
此方法可以获取DOM节点的父节点宽度,然后父节点可以设置成自适应的百分比或者其他方式如框架中的row>col栅格布局,由于此方法获取的宽度是像素,这样我们就可以直接赋值给echarts图表节点,赋值时记得拼接单位px
this.$refs["myChart"].style.width = `${width}px`;//width为父节点宽度,由于获取的是数值所以需要拼接单位,不然无效
那么重点来了,由于在此案例中我的echarts图表是放在modal对话框中的,而一开始modal节点一般是隐藏状态,如果底层用的是v-if就会涉及到DOM渲染先后的问题,如果还没有渲染之前就是使用DOM.parentNode.offsetWidth方法是获取不到的节点的宽度的,只能获取到一个0,但是翻看框架源代码之后发现是用的v-show也就是隐藏显示不涉及到DOM渲染,经过一番排查之后确认问题还是出在DOM渲染先后这里,所以我们在获取图表节点的时候得加一个异步回调函数定时器、$nexttick都可以,来确保他在渲染之后才获取父节点的宽度,而打开modal的地方也一样,需要加一个异步回调,来确保先打开再渲染
index.vue代码:
watch: {
detailModalState(status){
if(!status){
this.$refs["marketingDeatalRef"].destroy();
}
}
},
// 查看modal方法
lookDetail() {
this.detailModalState = true//此处要确保先打开modal再渲染
this.$nextTick(()=>{
this.$refs['marketingDeatalRef'].initCharts()//初始化图表的方法
})
},
modal.vue代码:
initCharts(){
this.$refs["lineEchartRef"].init();
}
//注意此方法非生命周期
destroy() {
this.$refs["lineEchartRef"].destroy();
},
echarts.vue代码:
<template>
<div ref="myChart" :style="{ height: '400px' }"></div>
</template>
<script>
import * as echarts from "echarts";
export default {
name: "",
data() {
return {
resizeFn:null,
};
},
mounted() {},
methods: {
init() {
this.$nextTick(() => {
let myChartDom = this.$refs["myChart"];
let width = this.$refs["myChart"].parentNode.offsetWidth; //获取父级节点的宽度
myChartDom.style.width = `${width}px`;//赋值给图表DOM
});
let myChart = echarts.init(this.$refs["myChart"]);
myChart.setOption({
title: {
text: "",
},
tooltip: {
trigger: "axis",
},
legend: {
data: ["日新增客户数", "活动参与客户数", "完成任务客户数"],
},
grid: {
left: "0%",
right: "0%",
bottom: "3%",
containLabel: true,
},
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: "category",
boundaryGap: true,
data: [
"2022-08-25",
"2022-08-26",
"2022-08-27",
"2022-08-28",
"2022-08-29",
"2022-08-30",
"2022-08-31",
],
},
yAxis: {
type: "value",
},
series: [
{
name: "日新增客户数",
type: "line",
stack: "Total",
data: [120, 132, 101, 134, 90, 230, 210],
},
{
name: "活动参与客户数",
type: "line",
stack: "Total",
data: [220, 182, 191, 234, 290, 330, 310],
},
{
name: "完成任务客户数",
type: "line",
stack: "Total",
data: [150, 232, 201, 154, 190, 330, 410],
},
],
});
this.resize = () => {//中转一下
let width = this.$refs["myChart"].parentNode.offsetWidth;
// myChartDom.style.width = `${width}px`;//可以直接赋值然后再调用echarts的resize方法
myChart.resize({ width: width + "px", height: "400px" }); //resize方法可以重设图表大小,可以传参设置
}
window.addEventListener("resize", this.resizeFn);//添加浏览器窗口大小变化事件,resize名字是固定的
},
// 为什么放在一个事件内而不是放在生命周期内,因为关闭modal的时候modal节没了获取不到节点大小,再调整窗口大小会报父级节点不可读的错误
// 通过监听modal状态来调用此方法
//注意此方法非生命周期钩子
destroy(){
//移除添加的resize事件,如果不移除这个事件会一直在,然后在其他页面调整窗口大小时会报错,关闭modal之后再调整窗口也会报错
window.removeEventListener("resize",this.resizeFn);
}
},
};
</script>
<style lang="less" scoped>
</style>
初始化大小:
缩放后: