問題:某個元件在週期mounted中呼叫了使用computed屬性getter來的全域性變數,該全域性變數為非同步請求的資料,在非路由進入頁面即重新整理該頁面時跳過了store的index.js中的請求資料函式,造成了呼叫資料失敗,得到為空。
問題修正: 解決: 正在用元件中附加檢測自己請求資料方法解決(有好的 方法可以評論區指教一下:)
原因: 重新整理頁面時仍然是先走app.vue,該非同步請求資料的方法在app的created中呼叫,所以store中的index.js中actions物件中定義的請求資料的方法並沒有被跳過,而是因為元件內第一次呼叫該資料的時候資料為空,拿不到資料,只有請求的資料返回時才會將資料二次set到對應的變數中。
預防: 這裡程式報錯是因為拿來的資料變數為物件型別,在未拿到資料時為undefined,此時對物件內屬性或方法呼叫時就會報錯。應當對需要深層呼叫的變數進行判空處理,防止程式出錯。
延展:
2018-5-24更新一下:
關於全域性請求來的變數,我們一般放在computed中用語法糖mapGetters來獲取,是因為computed計算屬性是基於它的快取依賴的,當依賴發生變化時,自然變數也就發生了變化。如果我們在元件中需要用到一個基於非同步請求資料的變數時,這個時候就要把它放在computed中。如下例:
我在store中封裝了一個非同步請求的方法
updateData ({ commit }) { Common.getAssets(ticket).then(response => { commit('initAssets', response.data.data) }) .catch(error => { console.log(error) }) }複製程式碼
這個時候我用到了一個變數叫overNews是由assets陣列和當前日期做了一系列比較判斷後賦值成功的,如果我直接在created中呼叫該方法,那麼這個變數就空了。所以我對assets進行了watch,然後將initOverNews放在監控的執行中。程式碼如下:
initOverNews(){ let overNews = []; this.assets && this.assets.map(curt => { if(curt.assetsLeader._id === this.userInfo._id){ if(compareAsc(new Date(), addWeeks(curt.createTime, curt.borrow_data)) === 1){ overNews.push({indexID: curt._id, operateType: '10',createTime: new Date(), tipsTxt: '資產' +curt.name + '已超期,請儘快歸還'}); } } }); this.$store.commit('initOverMsg', overNews); }複製程式碼
watch: { assets: function(){ this.asyncFlag++; },
//下面的這幾個是做別的判斷,不用理會 msg: function(){ this.asyncFlag++; }, userInfo: function(){ this.asyncFlag++; }, asyncFlag: function(){ if(this.asyncFlag>=3){ this.initOverNews(); } }, msgLength: function(){ this.initPop(); } }
複製程式碼
computed: { ...mapGetters([ 'assets', 'msg', 'overTipMsg', 'indexFlag', 'userInfo' ]), msgLength: function() { return this.msg?this.msg.length:0 + this.overTipMsg?this.overTipMsg.length:0; } // nowUrl: window.location.href }複製程式碼
同樣,在程式碼裡你也看到了msgLength這個我新增的計算屬性的變數,這樣,在非同步資料來的時候,msgLength就可以隨之更新而更新,同時,因為msgLength的變化而引起的的一系列邏輯處理也可以放在watch中。
小結: 計算屬性是基於它的依賴快取的。計算屬性在它的相關依賴發生改變時會重新取值,所以資料發生變化時,計算屬性的值會進行更新,相關的模板引用也會重新渲染。
這句話來自某個連結,可以點過去看。
今天就先寫到這,以後有坑持續更新,希望能幫到你們。