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

栏目: Objective-C · 发布时间: 5年前

内容简介::star:️ 更多前端技术和知识点,搜索订阅号问题复现:父组件中通过名为 source 的 prop 向子组件 Chart 传入数据

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

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

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

问题复现:父组件中通过名为 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 上出现的这种问题了。

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

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


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Adobe Dreamweaver CS5中文版经典教程

Adobe Dreamweaver CS5中文版经典教程

Adobe公司 / 陈宗斌 / 人民邮电 / 2011-1 / 45.00元

《Adobe Dreamweaver CS5中文版经典教程》由Adobe公司的专家编写,是AdobeDreamweavelCS5软件的官方指定培训教材。全书共分为17课,每一课先介绍重要的知识点,然后借助具体的示例进行讲解,步骤详细、重点明确,手把手教你如何进行实际操作。全书是一个有机的整体,它涵盖了Dreamweavercs5的基础知识、HTML基础、CSS基础、创建页面布局、使用层叠样式表、使......一起来看看 《Adobe Dreamweaver CS5中文版经典教程》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具