報錯解析 [Vue warn]: You may have an infinite update loop in a component render function.
阿新 • • 發佈:2018-11-07
結構
vue操作一個很有意思的報錯
[Vue warn]: You may have an infinite update loop in a component render function.
程式碼:
<template> <span class="show-filters" :class="show = !show"> {{ show ? '隱藏過濾器 ↑' :'顯示過濾器 ↓' }} </span> </template> <script> export default { data() { return { show: true } } }; </script>
分析
問題的本質
NOTE: render method is triggered whenever any state changes
即任何時候vue例項狀態的改變都會觸發渲染方法的執行
- 元件初始化時,將資料屬性show值為true
- 當渲染方法執行,內聯表示式
show = !show
改變了狀態 - 響應狀態show改變,重新執行render方法,企圖生成新的VNode節點(以便生成真實節點插入頁面)
- 於是產生的局面會無盡迴圈這樣:render - show改變 - render 重複執行步驟2-3-2
v-for
類似同樣的報錯,還很有可能在v-for指令中產生,如下
<div v-for="item in model.items" v-bind:class="test(item.result)">
{{item.id}}
</div>
vue部分
data() { return { accept: false, not_accept: false, }; }, methods: { test(result) { if (result == 'accept') { this.accept = true; this.not_accept = false; } else if (result == 'Not accept') { this.accept = false; this.not_accept = true; } else { console.log(result); } return { success: this.accept, danger: this.not_accept, }; }, },
- 也會出現如題報錯,其原因是在for迴圈中 (render - test - render )間接修改了data響應資料而且沒有終止條件。但是記住狀態的改變會導致渲染方法的執行,上述兩種情況的相同點在於,執行渲染時,又會改變狀態,於是又渲染,遲遲不能生成真實節點,不休了。
解決方案
對同一依賴響應資料屬性在同一例項的生命週期內只作一次變更。
比如:對示例一,將屬性繫結改為vue事件繫結,事件是在下一次tick執行渲染
對於示例二,for指令通常只用來讀取資料,而非寫入響應資料。如需寫入資料,無論直接還是間接操作都不要改變響應資料,如下所示:
methods: {
test(result) {
let accept;
if (result == 'accept') {
accept = true;
} else if (result == 'Not accept') {
accept = false;
} else {
console.log(result);
}
return {
success: accept,
danger: !accept,
};
},
}
小結
- 慎用內聯表示式,對於自定義vue屬性而言,它會被渲染器自執行,上述兩個小錯誤同樣報錯便如此
- 儘可能用事件改變狀態 ,驅動頁面渲染重繪