頻道欄目
首頁 > 程序開發 > web前端 > HTML/CSS > 正文
組件中watchprops根據v-if動態判斷并掛載DOM的問題-前端和Node學習筆記-SegmentFault思否
2019-05-11 22:05:10           
收藏   我要投稿

20190511004013.png

組件中 watch props 根據 v-if 動態判斷并掛載 DOM 的問題

?? 更多前端技術和知識點,搜索訂閱號 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 的 p,用以初始化 echarts 實例

<p v-if="source && source.length" id="main" ref="main"></p>
<p vi-else>none</p>

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 數據雖然有了,但 p 還并未掛載,因此 echarts 無法完成初始化

那么想當然的我們就會去在 mounted 生命周期函數中調用 setOpts 方法:

mounted () {
    console.log(this.source, this.$refs.main) // [] undefined
    this.setOpts()
  },

這樣也是錯的,因為模板語法中使用了 v-if,那么當 source 并未滿足條件的時候,p 當然也不會掛載。因此 p 仍然無法訪問到。

Error in mounted hook: "TypeError: Cannot read property 'getAttribute' of undefined"

解決辦法是要么去掉 v-if 要么換另一種寫法

有時我們需要在沒有數據的情況下增加一個占位標簽用來展示一些額外的提醒信息,如“暫未獲取到數據”等。那么去掉 v-if 肯定不行。

既然如此我們保留 v-if 但寫法有所改變:

修改 Chart 組件:

<template>
  <p>
    <p id="main" ref="main"></p>
  </p>
</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>
  <p>
    <Chart :source="chartData" v-if="flag"></Chart>
    <p v-else>none</p>
  </p>
</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 上出現的這種問題了。

JS 菌公眾賬號

請關注我的訂閱號,不定期推送有關 JS 的技術文章,只談技術不談八卦 ??

點擊復制鏈接 與好友分享!回本站首頁
相關TAG標簽
上一篇:積夢前端的路由方案ruled-router-題葉-SegmentFault思否
下一篇:10個有趣的javascript和css庫(2019年最新)-CSS技術學習-SegmentFault思否
相關文章
圖文推薦
文章
推薦
點擊排行

關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

重庆快乐十分开奖记录