查看: 3683|回复: 3

Vue Highcharts动态饼图数据不显示原因与延迟渲染修复

[复制链接]
发表于 4 天前 | 显示全部楼层 |阅读模式
在 Vue 项目中用 Highcharts 做动态饼图时,常见现象是页面能打开但图表不显示,或请求返回后数据没有绘制出来。原文的实现由 chart.vue 子组件、options.js 配置模型和父页面三部分组成。子组件接收 id 与 option 两个 props,mounted 中的静态创建被注释,改由 reload() 方法通过 setTimeout 延迟 200ms 调用 HighCharts.chart(this.id,this.option);配置模型用 Options 构造函数保存 pie 配置,funcc(op) 用 Object.assign 合并传入配置,series[0].data 初始为空数组。
  1. methods: {
  2.   reload(){
  3.     setTimeout(() => {
  4.       HighCharts.chart(this.id,this.option)
  5.     }, 200);
  6.   }
  7. }
复制代码

父页面在 created 中调用 chartPie1()/chartPie2(),用 Promise 包住 axios.get("highcharts"),请求成功后把返回数据赋给 options.pie.series[0].data,再执行 this.option1 = options.pie,之后在 then 中通过 ref 手动调用子组件方法创建饼图/柱图。问题出在生命周期时序:父页面 created 时 option1/option2 还是 null,子组件 mounted 早于异步数据返回和赋值;Highcharts 创建时需要容器和配置,若创建过早则拿不到 series 数据,后续只改 options 对象也不会自动重绘。原文在子组件加 200ms 延迟,就是等 axios 返回并赋值后再创建。
  1. options.funcc({
  2.   pie: {
  3.     title: { text: '浏览器访问量' },
  4.     series: [{ type: 'pie', name: '浏览器访问量占比', data: [] }]
  5.   }
  6. });
  7. axios.get("highcharts").then(({data}) => {
  8.   options.pie.series[0].data = data;
  9. });
  10. this.option1 = options.pie;
  11. resolve();
复制代码

排查时先核对 chartPie1 的 then 中调用的是 this.$refs.XChart1.me(),而子组件实际暴露的方法名是 reload(),chartPie2 调用的是 reload();方法名不一致会导致调用失败或无图表。还要确认容器 id 唯一、option 已从 null 变为配置、axios 返回数据符合 Highcharts series.data 格式、ref 名称与子组件一致、创建调用发生在数据赋值之后。原文的 setTimeout(200) 只是规避竞态,网络慢于 200ms 时仍可能失败;从原文代码可推导更稳妥的做法是等 axios then 中数据赋值完成并 resolve,再在父级 then 或 $nextTick 后调用创建/更新,同时保证方法名一致。延迟渲染适合数据量小、请求稳定的演示场景;生产环境应把创建时机绑定到数据就绪事件,而不是固定延时。原文同时完成饼图和柱图,柱图配置模型未贴出,但调用链与饼图一致:请求数据赋给 options1.chart.series[0].data,this.option2 = options1.chart,然后 refs.XChart2.reload()。
回复

使用道具 举报

发表于 4 天前 | 显示全部楼层

Re: Vue Highcharts动态饼图数据不显示原因与延迟渲染修复

这篇排查思路挺完整,关键点抓得准:问题核心不是 Highcharts 本身,而是 Vue 生命周期和异步请求的时序。父页面 created 时配置还是 null,子组件 mounted 又早于 axios 返回,固定 200ms 只能算临时规避,网络一慢就会失效。更稳的做法是把创建或更新动作放到数据赋值完成之后,比如在 then 里赋值后通过 nextTick 再调用子组件方法,同时确保 chartPie1 调用的方法名和子组件实际暴露的 reload 保持一致。另外建议子组件里做一下判断:图表实例不存在就创建,已存在就用 setData 或 update 更新,而不是只改 options 对象,因为 Highcharts 不会自动感知普通对象变化。容器 id 唯一、ref 名称一致、数据格式符合 series.data 这些检查点也很实用。延迟渲染用于演示没问题,生产环境还是绑到数据就绪事件更可靠。
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层

Re: Vue Highcharts动态饼图数据不显示原因与延迟渲染修复

这个排查思路挺清晰的,问题核心就是生命周期和异步时序没对齐:父页面 created 时配置还是 null,子组件 mounted 又早于 axios 返回,固定 200ms 只能算演示阶段的临时规避,网络一慢还是会翻车。 比较稳妥的做法确实是把创建时机绑到数据赋值完成之后,比如 axios then 里赋值完再 nextTick 后调用 ref 的 reload,或者子组件里 watch option 变化后更新/创建,而不是靠 setTimeout 赌请求速度。另外方法名不一致这个坑很典型,chartPie1 调 me()、子组件暴露 reload(),这种低级但很容易漏。再就是重复调用时要留意首次创建和后续更新是不是同一套逻辑,容器 id 唯一、ref 名一致、数据格式符合 series.data 这些检查点都挺实用。整体看这篇把现象、原因和排查路径讲得比较完整,生产环境不建议固定延迟这个结论也认同。
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层

Re: Vue Highcharts动态饼图数据不显示原因与延迟渲染修复

楼主这个排查思路挺清楚的,问题核心确实在于父页面 created 时 option1、option2 还是 null,而子组件 mounted 又早于 axios 异步数据返回,导致 Highcharts 创建时拿不到 series 数据,后面再改 options 对象也不会自动重绘。用 setTimeout 延迟 200ms 能缓解演示场景下的竞态,但它不是根治办法,网络慢一点仍然会失败。 比较稳妥的做法还是把创建时机绑定到数据就绪:axios 请求成功并完成 options.pie.series[0].data 赋值、this.option1 = options.pie 之后,再 resolve,然后在父级 then 或 $nextTick 后通过 ref 调子组件方法创建图表。同时要特别注意 chartPie1 的 then 里调用的是 this.$refs.XChart1.me(),而子组件实际暴露的是 reload(),方法名不一致会直接导致调用失败或无图,这个排查点很关键。 另外可以顺手确认几个点:容器 id 唯一、ref 名称和子组件一致、option 已经从 null 变成配置、axios 返回数据符合 Highcharts series.data 的格式、创建调用一定发生在数据赋值之后。柱图调用链和饼图一致,也要保证 options1.chart.series[0
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-27 18:10 , Processed in 0.030888 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部