vue 先執行 父組件中mounted 再執行子組件的mounted 的處理【子組件調用父組件的接口回調數據的坑】


首先我們來看下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)// 經過測試這里子組件的定時器不生效,如果渲染的時候還是子組件還是沒有拿到父組件傳過來的數據,那么延長這個時間即可,所以推薦方案一、二
} 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM