问题复现:父组件中通过名为 source 的 prop 向子组件 Chart 传入数据
<Chart :source="chartData"></Chart>
import Chart from '../components/Chart' export default { name: 'Home', components: { Chart }, data () { return { chartData: [] } }, mounted () { setTimeout(() => { this.chartData = [ [89.3, 58212, 'Matcha Latte'], [57.1, 78254, 'Milk Tea'], [74.4, 41032, 'Cheese Cocoa'], [50.1, 12755, 'Cheese Brownie'], [89.7, 20145, 'Matcha Cocoa'], [68.1, 79146, 'Tea'], [19.6, 91852, 'Orange Juice'], [10.6, 101852, 'Lemon Juice'], [32.7, 20112, 'Walnut Brownie'] ] }, 2000) } }
子组件接收 source 数据当存在且至少有一条数据的时候,创建 id 为 main 的 div,用以初始化 echarts 实例
<div v-if="source && source.length" id="main" ref="main" style="width: 600px;height: 400px;"></div> <div vi-else>none</div>
Chart 组件通过接收数据 watch prop 的变化动态的调用 echarts 的 setOptions 方法,最终渲染数据。
export default { // ... watch: { source (newVal, oldVal) { this.setOpts() } }, props: ['source'], methods: { setOpts () { let myChart = this.$echarts.init(this.$refs.main) myChart.setOption({ dataset: { // ... source: this.source }, // ... }) } } }
如果直接这么写必定报错:
Error in callback for watcher "source": "TypeError: Cannot read property 'getAttribute' of undefined"
在代码中增加一行代码:
watch: { source (newVal, oldVal) { console.log(newVal, this.$refs.main) // [Array ...] undefined this.setOpts() } },
启示 source 数据虽然有了,但 div 还并未挂载,因此 echarts 无法完成初始化
那么想当然的我们就会去在 mounted 生命周期函数中调用 setOpts 方法:
mounted () { console.log(this.source, this.$refs.main) // [] undefined this.setOpts() },
这样也是错的,因为模板语法中使用了 v-if,那么当 source 并未满足条件的时候,div 当然也不会挂载。因此 div 仍然无法访问到。
Error in mounted hook: "TypeError: Cannot read property 'getAttribute' of undefined"
解决办法是要么去掉 v-if 要么换另一种写法
有时我们需要在没有数据的情况下增加一个占位标签用来展示一些额外的提醒信息,如“暂未获取到数据”等。那么去掉 v-if 肯定不行。
既然如此我们保留 v-if 但写法有所改变:
修改 Chart 组件:
<template> <div> <div id="main" ref="main" style="width: 600px;height: 400px;"></div> </div> </template>
我们只需要一个 source 数据源,当 mounted 的时候调用 setOpts 方法,当 watch 数据变化的时候再次调用以更新数据
export default { name: 'Chart', props: ['source'], mounted () { this.setOpts() }, watch: { source () { this.setOpts() } }, methods: { setOpts () { let myChart = this.$echarts.init(this.$refs.main) myChart.setOption({ dataset: { dimensions: ['score', 'amount', 'product'], source: this.source }, xAxis: { type: 'category' }, yAxis: {}, series: [ { type: 'bar', encode: { x: 'product', y: 'amount' } } ] }) } } }
v-if 的判断我们把他移出去了我们判断 chartData 是否获取到,一旦获取到数据,马上加载 Chart 组件,这样就可以避开在组件内部调用 v-if 带来的问题:
<template> <div> <Chart :source="chartData" v-if="flag"></Chart> <div v-else>none</div> </div> </template> import Chart from '../components/Chart' export default { name: 'Home', components: { Chart }, data () { return { chartData: [], flag: false } }, methods: { getData () { setTimeout(() => { this.chartData = [ [89.3, 58212, 'Matcha Latte'], [57.1, 78254, 'Milk Tea'], [74.4, 41032, 'Cheese Cocoa'], [50.1, 12755, 'Cheese Brownie'], [89.7, 20145, 'Matcha Cocoa'], [68.1, 79146, 'Tea'], [19.6, 91852, 'Orange Juice'], [10.6, 101852, 'Lemon Juice'], [32.7, 20112, 'Walnut Brownie'] ] this.flag = true }, 2000) } }, mounted () { this.getData() } }
另外还可将 Chart 组件和站位标签一同封装成一个 ChartWrapper。
这样就不会因在组件内部调用 watch 监听 props 的变化动态 v-if 判断并挂载数据到 DOM 上出现的这种问题了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]