【實戰】Vue 中 Props 值因異步獲取致使的報錯問題解析

問題簡述

父子組件經過 props 傳值,當所傳值須要異步請求獲取時,子組件在掛載完成階段(mounted),拿不到props值javascript

具體實例描述

父組件:vue

<template>
    <div>
        <son :father-data="fatherData"/>
    </div>
</template>

<script>
import son from './son.vue'

export default {
	name: "Father",
    component: {
      son  
    },
    data: {
        fatherData : {} 
    },
    created() {
        // 假設已經引入了 axios 組件,在這裏發起異步請求
        this.axios.get('http://some_api/data').then((res) => {
            this.fatherData = res.data.data  // 假設獲取到的值爲 "{ name: 'hehe'}}"
        }).catch((err) => {
            console.log(err.data.errmsg)  
        })
    },
})
</script>
複製代碼

子組件:java

<template>
    <div>
        <p>son component</p>
    </div>
</template>

<script type="text/javascript">
export default {
	name: "Son",
    props: {
        fatherData: {
            type: Object,
            default: () => {}
        }
    },
    mounted() {
        console.log(this.fatherData) // 輸出結果爲:{}
    },
    watch: {
        fatherData(newV, oldV) {
            console.log(newV) // 輸出結果爲: {name: 'hehe'}
        }
    }
})
</script>
複製代碼

問題根源

上面的代碼,咱們從生命週期的角度,從頭走一遍:ios

  1. 父組件開啓生命週期
  2. 父組件進行到 created 階段,完成 fatherData 的初始化,併發出了異步請求獲取數據。
  3. 父組件進行到 beforeMount 階段,發現有引用子組件,因而開始編譯子組件
  4. 子組件開啓生命週期
  5. 子組件進行到 created 階段,完成 props 的初始化(其值爲 fatherData的初始值 {})
  6. 子組件進行到 mounted 階段,輸出 props
  7. 父組件進行到 mounted 階段
  8. 異步請求返回數據,並更新了 fatherData (忽略 beforeUdate 和 updated,不是重點)
  9. 子組件中 watch 檢測到 fatherData 值變化,觸發函數輸出 {name: 'hehe'}
沙盒模擬地址

能夠看出,有三個關鍵因素決定了這種結果:axios

  1. Js 異步機制
  2. Vue 生命週期中 Props 的建立機制(在 created 完成)
  3. Vue 生命週期中父子組件的掛載機制(先子後父)

解決思路

子組件應增長 v-if 判斷條件,在異步請求返回數據後進行編譯渲染。api

相關文章
相關標籤/搜索