项目场景:
点击展开卡片,卡片内容为echart的图表。
默认不展开卡片。
问题描述
点击展开后,内容 空白,不显示图表。
原因分析:
因为默认不展开,因此图表无法直接渲染,需要添加对应的方法去渲染图表。
虽然页面在一开始就获取了图表所需的数据,甚至可能已经做了初始化。但是要注意,此时卡片并没有展开,因此dom没有,所以初始化是失败的!!!就导致了点击展开以后内容空白,图表无法渲染。
解决方案:
需要根据卡片展开去渲染数据!
有两个方法可以去做
一:watch监听卡片的展开,监听到展开以后进行图表渲染
二:添加卡片的点击事件,在点击事件里面添加渲染逻辑
方法一:watch
处理逻辑
用户点击 collapse 标题
↓
van-collapse 内部修改 activeNames(展开)
↓
watch 监听到 activeNames 变化
↓
$nextTick:等待 DOM 更新完成
↓
面板已展开,容器有宽高
↓
初始化图表
↓渲染成功
特点: van-collapse 自主改变数据,watch 被动响应,逻辑自然。
这里是监听到卡片展开的消息就出发了watch代码块,使用$nextTick是为了确保dom更新完成使得图表渲染所需的高宽存在,否则图表可能会渲染失败!!!
ctiveNames (newValue) { // 监听 '1'(卡片) 是否被展开 if (newValue && newValue.includes('1')) { this.$nextTick(() => { if (this.completionChart) { // 图表已存在,调整尺寸 this.completionChart.resize() } else if (this.completionChartReady) { // 数据已加载,立即初始化图表 this.initCompletionChart() } }) } }方法二:点击事件
处理逻辑
用户点击
↓
click handler 执行(同步):
1. this.activeNames = ['1'] → 主动改变数据
2. this.$nextTick(() => { → 等待 DOM 更新完成
initCompletionChart() → 面板已展开,容器有宽高
})
↓
渲染成功
1、用 van-collapse 的 @change 事件
<van-collapse v-model="activeNames" @change="onCollapseChange"> <van-collapse-item name="1"> <template #title> <div class="firstContentTitle0"> <span class="firstContentTitle1"> <van-image :src="require('@/assets/icon/ico_two_done.svg')" /> </span> <span class="firstContentTitle2">各分公司完成情况</span> </div> </template> <div class="firstContentFrame"> <div class="chart-container" ref="completionChart"></div> </div> </van-collapse-item> </van-collapse>2、对应的method
methods: { onCollapseChange() { if (this.activeNames && !this.activeNames.includes('1')) { this.activeNames.push('1') this.$nextTick(() => { if (this.completionChart) { this.completionChart.resize() } else if (this.completionChartReady) { this.initCompletionChart() } }) } } }错误示例
点击事件逻辑和watch处理代码一致,图表在第一次展开的时候会是空白,第二次展开才能正常渲染!!!
methods: { onCollapseChange() { if (this.activeNames && this.activeNames.includes('1')) { this.$nextTick(() => { if (this.completionChart) { this.completionChart.resize() } else if (this.completionChartReady) { this.initCompletionChart() } }) } } }错误原因:
因为点击事件发生时,卡片的展开标识还没有更新,而是优先执行点击事件的逻辑
顺序如下:
用户点击->执行代码块->更新卡片展开标识
由此可知,此时activename并没有‘1’,所以其实无法执行代码块,就算不加if (this.activeNames && this.activeNames.includes('1'))的判断,他也无法成功渲染,因为卡片并没有成功展开呢,dom没有更新,没有高宽给到echart渲染图表!
解决方案(点击事件代码块):
手动修改卡片展开标识->dom更新完毕->渲染图表
总结
watch直接监听到卡片展开标识更新以后,才执行watch代码块,要注意使用$nextTick等待dom更新完成以后再执行echart渲染,(是因为echart渲染强关联dom的高宽!!!否则直接执行是可以的!!!!)
点击事件则是先触发点击事件代码块,才到更新展开标识。按照这个逻辑,首次展开是无法获取图表渲染所必须的高宽,因此无法成功!
所以需要将展开标识的更新前置到点击事件代码块,然后后面逻辑与watch一致(dom更新,图表渲染)
两者逻辑上略有不同,因此操作也略不同!