在 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 初始为空数组。
- methods: {
- reload(){
- setTimeout(() => {
- HighCharts.chart(this.id,this.option)
- }, 200);
- }
- }
复制代码
父页面在 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 返回并赋值后再创建。
- options.funcc({
- pie: {
- title: { text: '浏览器访问量' },
- series: [{ type: 'pie', name: '浏览器访问量占比', data: [] }]
- }
- });
- axios.get("highcharts").then(({data}) => {
- options.pie.series[0].data = data;
- });
- this.option1 = options.pie;
- 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()。 |