vue中父組件異步數(shù)據(jù)通過props方式傳遞給子組件,子組件接收不到的問題
問題描述
組件化開發(fā)中經(jīng)常用到父子組件的通信,父傳子子傳父等數(shù)據(jù)的操作,如果父組件的數(shù)據(jù)是發(fā)請求從后端獲取的異步數(shù)據(jù),那么父組件將這個(gè)數(shù)據(jù)傳遞給子組件的時(shí)候,因?yàn)槭钱惒綌?shù)據(jù),就會(huì)出現(xiàn)父組件傳遞過去了,但是子組件mounted鉤子初始情況下是接收不到的問題。本篇文章記錄了一下這個(gè)問題的解決方案。
在說這個(gè)問題之前,我們先來回顧一下父子組件的生命周期
父子組件生命周期執(zhí)行順序
加載渲染數(shù)據(jù)過程父組件
beforeCreate -->
父組件 created -->
父組件 beforeMount -->
子組件 beforeCreate -->
子組件 created -->
子組件 beforeMount -->
子組件 mounted -->
父組件 mounted -->
更新渲染數(shù)據(jù)過程
父組件 beforeUpdate -->
子組件 beforeUpdate -->
子組件 updated -->
父組件 updated -->
銷毀組件數(shù)據(jù)過程
父組件 beforeDestroy -->
子組件 beforeDestroy -->
子組件 destroyed -->
父組件 destroyed
可以這樣理解,父組件生命周期中會(huì)先看看子組件的生命周期有沒有走完,子組件生命周期走完了,才會(huì)走父組件的生命周期。
問題分析
我們模擬一下父子組件通信的過程,寫個(gè)小demo??纯丛谧咏M件中的mounted鉤子中能不能接收到父組件傳遞過來的數(shù)據(jù)
父組件代碼
<template>
<div id="app">
<child :msg="msg"></child>
</div>
</template>
<script>
import child from "./views/child";
export default {
name: "App",
components: {
child,
},
data() {
return {
msg: "", // 我們要把父組件從接口獲取的數(shù)據(jù)存到data中的msg里面,然后再傳遞給子組件
};
},
created() {
// 用定時(shí)器模擬發(fā)請求異步獲取后端接口的數(shù)據(jù)
setTimeout(() => {
this.msg = "666";
}, 200);
},
};
</script>
子組件代碼
<template>
<div>
<h2>{{msg}}</h2>
</div>
</template>
<script>
export default {
props:{
msg:{
type:String,
default:''
}
},
mounted() {
console.log('mounted鉤子中接收',this.msg);
},
}
</script>
最終在mounted鉤子中會(huì)實(shí)現(xiàn),我們會(huì)發(fā)現(xiàn)打印不出來,如下圖
當(dāng)然如果是同步的數(shù)據(jù)傳遞給子組件,子組件的mounted鉤子是能接收到,能打印出來的,這里就不演示了,因?yàn)槲覀冏鲰?xiàng)目開發(fā)的數(shù)據(jù)大多數(shù)都輸從后端的接口中獲取的異步數(shù)據(jù)的。
因?yàn)楦附M件傳遞給子組件的數(shù)據(jù),可能我們還要加工一下再使用,所以在mounted鉤子中獲取父組件傳遞過來的數(shù)據(jù)是一定要做的。那么,這里為什么mounted鉤子中打印不出來父組件傳遞過來的數(shù)據(jù),但是props最終接收到了,頁面最終還渲染出來了么?
原因淺析
我們知道,mounted鉤子默認(rèn)加載只會(huì)執(zhí)行一次,由于數(shù)據(jù)是要等到200毫秒以后才能拿到,那么子組件的mounted鉤子執(zhí)行的時(shí)候,還沒有拿到父組件傳遞過來的數(shù)據(jù),但是又必須要打印出來this.msg的結(jié)果,那這樣的話,就只能去打印props中的msg的默認(rèn)值空字符串了,所以打印的結(jié)果是一個(gè)空字符串,比如,我們在子組件中這樣打印就知道this.msg是不是空字符串了
mounted() {
console.log('mounted鉤子中接收', this.msg == '');
},
打印結(jié)果圖如下
但是props是可以等的,是可以拿到異步的數(shù)據(jù)渲染的。所以就出現(xiàn)了上述的結(jié)果,有問題解決問題,接下來說一下解決這樣的問題的方案
方案一 使用v-if控制子組件渲染的時(shí)機(jī)
思路其實(shí)很簡單,就是初始還沒拿到后端接口的異步數(shù)據(jù)的時(shí)候,不讓組件渲染,等拿到的時(shí)候再去渲染組件。使用v-if="變量"去控制,初始讓這個(gè)變量為false,這樣的話,子組件就不會(huì)去渲染,等拿到數(shù)據(jù)的時(shí)候,再讓這個(gè)變量變成true,這樣的話,組件就會(huì)去渲染,此時(shí)數(shù)據(jù)也已經(jīng)得到了,這樣的話,在子組件的mounted鉤子中就拿到父組件傳過來的異步數(shù)據(jù)了。代碼如下
父組件
<template>
<div id="app">
<child :msg="msg" v-if="isGetData"></child>
</div>
</template>
<script>
import child from "./views/child";
export default {
name: "App",
components: {
child,
},
data() {
return {
msg: "",
isGetData:false // 初始為false,就不會(huì)被渲染對應(yīng)的子組件
};
},
created() {
// 用定時(shí)器模擬發(fā)請求異步獲取后端接口的數(shù)據(jù)
setTimeout(() => {
this.msg = "666";
this.isGetData = true // 拿到數(shù)據(jù)以后,再把isGetData置為true,這樣的話,組件就會(huì)被渲染啦,數(shù)據(jù)也就會(huì)被傳遞過去啦
}, 200);
},
};
</script>
子組件
這種方式,子組件不用動(dòng)代碼,在父組件中去做控制即可
但是這種方式有一個(gè)小小的缺點(diǎn),就是最終效果會(huì)顯得組件有些延遲才出現(xiàn)效果。因?yàn)楫惒綌?shù)據(jù)是從后端的接口獲取的,如果接口時(shí)間長一些的話,最終效果渲染也會(huì)慢一點(diǎn),但是!??!一般情況下,后端的接口速度都會(huì)控制在幾十到幾百毫秒的時(shí)間,一般情況下,不會(huì)出現(xiàn)好幾秒,甚至幾十秒的接口,所以瑕不掩瑜,這種方式不影響我們使用
方案二 子組件使用watch監(jiān)聽父組件傳遞過來的數(shù)據(jù)
父組件
這種方式父組件正常傳遞數(shù)據(jù)即可,不需要做什么代碼處理,只要在子組件中加一個(gè)監(jiān)聽即可
子組件文章來源:http://www.zghlxwxcb.cn/news/detail-402228.html
<template>
<div>
<h2>{{ editMsg }}</h2>
</div>
</template>
<script>
export default {
props: {
msg: {
type: String,
default: "",
},
},
watch: {
// 監(jiān)聽到父組件傳遞過來的數(shù)據(jù)后,加工一下,
// 存到data中去,然后在頁面上使用
msg(newnew, oldold) {
console.log("監(jiān)聽", newnew, oldold);
this.editMsg = "---" + newnew + "---";
},
},
data() {
return {
editMsg: "",
};
},
};
</script>
看一下這種方式對應(yīng)的效果圖文章來源地址http://www.zghlxwxcb.cn/news/detail-402228.html
到了這里,關(guān)于vue中父組件異步數(shù)據(jù)通過props方式傳遞給子組件,子組件接收不到的問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!