博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
组件中 watch props 根据 v-if 动态判断并挂载 DOM 的问题
阅读量:6846 次
发布时间:2019-06-26

本文共 3647 字,大约阅读时间需要 12 分钟。

组件中 watch props 根据 v-if 动态判断并挂载 DOM 的问题

⭐️ 更多前端技术和知识点,搜索订阅号 JS 菌 订阅

问题复现:父组件中通过名为 source 的 prop 向子组件 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 实例

none
复制代码

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 组件:

复制代码

我们只需要一个 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 带来的问题:

复制代码
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 上出现的这种问题了。

请关注我的订阅号,不定期推送有关 JS 的技术文章,只谈技术不谈八卦 ?

转载于:https://juejin.im/post/5cd5a995f265da039f0f2da4

你可能感兴趣的文章
GoJS教程:链接模版
查看>>
QListWidget方式显示缩略图
查看>>
金三银四:蚂蚁金服JAVA后端面试题及答案之二面
查看>>
Ubuntu 外网不通解决方案
查看>>
OSChina 周六乱弹 —— 历史总是惊人的相似
查看>>
MySQL 大小写
查看>>
div块上下左右居中
查看>>
eclipse远程debug tomcat
查看>>
CentOs6.5基本环境配置(六):Maven配置
查看>>
Python 创建Django项目
查看>>
JS获取当前项目的根路径
查看>>
操作系统引导区代码
查看>>
程序员有五种错误不应犯
查看>>
无线认证知识点
查看>>
基于python的REST框架eve测试与mongodb的数据操作
查看>>
epoll模型的理解封装与应用
查看>>
Lync 2013部署图片赏析-证书服务安装配置
查看>>
HTML5 本地缓存 (web存储)
查看>>
tomcat redis session共享(包含redis安全设置)
查看>>
iptables中DNAT、SNAT和MASQUERADE的作用
查看>>