首先我們來看下vue 的渲染等執行順序
//加載渲染過程 父組件 beforeCreate 父組件 created 父組件 beforeMount 子組件 beforeCreate 子組件 created 子組件 beforeMount 子組件 mounted 父組件 mounted //更新過程 父組件 beforeUpdate 子組件 beforeUpdate 子組件 updated 父組件 updated //銷毀過程 父組件 beforeDestroy 子組件 beforeDestroy 子組件 destroyed 父組件 destroyed
但是在我們實際開發的的業務中,經常存在先父組件中請求接口,拿到數據再傳給子組件進行渲染的情況,由於vue先執行mounted再執行父組件的執行順序,所以在子組件在渲染時拿不到父組件的接口回調回來的數據,這時可以有以下三種解決方法:
方案一:
1、在父組件請求成功后再初始化渲染子組件,使用用子組件時添加v-if="flag"
2、flag初始化為:false.
3、在請求成功后修改flag為true。
//父組件 <template> <div class="world-scroll-table"> <ScrollTable :dealList="dealList" ref="table" v-if="flag" /> </div> </template> <script> import ScrollTable from './components/ScrollTable' import { getAction } from '@api/manage' export default { components: { ScrollTable, }, data() { return { flag:false, dealList:[], url: { dealList:'/bitcoin/bigScreen/pendingBtc'//最新交易通告 }, } }, mounted() { this.initDealList() window.parentMounted = this._isMounted//方案3第一步 }, methods: { /* * 初始化最新交易通告數據 */ initDealList() { getAction(this.url.dealList) .then((res) => { var arr = []; for(let i=0;i<res.length;i++){ arr.push([res[i].txid, res[i].timeDate, res[i].fee]) } this.dealList = arr this.flag =true }) .catch((err) => { this.$message.error(err) }) }, }
//子組件 <template> <div class="scroll-table"> <img src="@/assets/bigScreen/kuang-bg.png" class="scroll-table-bg" /> <dv-scroll-board :config="config" class="scroll-table-table" /> </div> </template> <script> export default { props: { dealList: { type: Array, default: [], }, }, data() { return { config: {}, header: ['交易哈希', '交易時間', '交易費'], data: [], } }, mounted() { this.config = { header: this.header, data: this.dealList, rowNum: 5, // 表行數 waitTime: 2000, // 輪播時間間隔(ms) align: ['center'], columnWidth: [50], index: true, indexHeader: '', headerBGC: 'transparent', // 表頭背景色 oddRowBGC: '', // 偶數行背景色 evenRowBGC: 'rgba(85, 156, 178, 0.1)', // 奇數行背景色 } }, } </script> <style lang="less" scoped> .scroll-table { position: relative; /deep/.dv-scroll-board .header { height: 35px; } /deep/.scroll-table-table { position: absolute; top: 44px; width: 585px; height: 328px; padding: 0 10px; .header { font-size: 16px; font-family: Microsoft YaHei; font-weight: bold; color: #ffffff; } .row-item { font-size: 14px; font-family: Microsoft YaHei; font-weight: 400; color: #bfc3c4; } } } </style>
方案二:
1、在子組件中使用watch監聽,當dealList數據變化(獲取到父組件傳遞過來的數據)時再渲染
//父組件 <template> <div class="world-scroll-table"> <ScrollTable :dealList="dealList" ref="table" /> </div> </template> <script> import ScrollTable from './components/ScrollTable' import { getAction } from '@api/manage' export default { components: { ScrollTable, }, data() { return { dealList:[], url: { dealList:'/bitcoin/bigScreen/pendingBtc'//最新交易通告 }, } }, mounted() { this.initDealList() }, methods: { /* * 初始化最新交易通告數據 */ initDealList() { getAction(this.url.dealList) .then((res) => { var arr = []; for(let i=0;i<res.length;i++){ arr.push([res[i].txid, res[i].timeDate, res[i].fee]) } this.dealList = arr }) .catch((err) => { this.$message.error(err) }) }, }
<template> <div class="scroll-table"> <img src="@/assets/bigScreen/kuang-bg.png" class="scroll-table-bg" /> <dv-scroll-board :config="config" ref="scrollBoard" class="scroll-table-table" /> </div> </template> <script> export default { props: { dealList: { type: Array, default: [], }, }, data() { return { config: {}, header: ['交易哈希', '交易時間', '交易費'], data: [], } }, mounted() {}, methods:{ initTable(){ this.config = { header: this.header, data: this.dealList, rowNum: 5, // 表行數 waitTime: 2000, // 輪播時間間隔(ms) align: ['center'], columnWidth: [50], index: true, indexHeader: '', headerBGC: 'transparent', // 表頭背景色 oddRowBGC: '', // 偶數行背景色 evenRowBGC: 'rgba(85, 156, 178, 0.1)', // 奇數行背景色 } } }, watch:{ dealList:{ deep:true, handler:function(){ this.initTable() } } } } </script>
方案三:
【思路】 通過打印 this 發現,有一個 _isMounted 屬性,表示當前是否掛載完畢(true:掛載完畢,false:沒有掛載完成),在父組件掛載前將 _isMounted 存在 window 中,掛載后更新 _isMounted。在子組件 mounted 中添加定時器,根據 _isMounted 判斷是否執行初始化方法。
// 父組件 beforeMount() { window.parentMounted = this._isMounted // _isMounted是當前實例mouned()是否執行 此時為false,實際使用時這步可以不要 }, mounted() { this.initDealList() //該方法是去請求接口拿到回調數據 window.parentMounted = this._isMounted // _isMounted是當前實例mouned()是否執行 此時為true }
// 子組件 mounted() { let pMountedTimer = window.setInterval(() => { if (window.parentMounted ) { window.clearInterval(pMountedTimer) // 下面就可以寫子組件想在mounted時執行代碼(此時父組件的mounted已經執行完畢) this.config = { header: this.header, data: this.dealList, rowNum: 5, // 表行數 waitTime: 2000, // 輪播時間間隔(ms) align: ['center'], columnWidth: [50], index: true, indexHeader: '', headerBGC: 'transparent', // 表頭背景色 oddRowBGC: '', // 偶數行背景色 evenRowBGC: 'rgba(85, 156, 178, 0.1)', // 奇數行背景色 } } }, 2000)// 經過測試這里子組件的定時器不生效,如果渲染的時候還是子組件還是沒有拿到父組件傳過來的數據,那么延長這個時間即可,所以推薦方案一、二
}