1. 程式人生 > >報錯解析 [Vue warn]: You may have an infinite update loop in a component render function.

報錯解析 [Vue warn]: You may have an infinite update loop in a component render function.

結構

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例項狀態的改變都會觸發渲染方法的執行

  1. 元件初始化時,將資料屬性show值為true
  2. 當渲染方法執行,內聯表示式show = !show改變了狀態
  3. 響應狀態show改變,重新執行render方法,企圖生成新的VNode節點(以便生成真實節點插入頁面)
  4. 於是產生的局面會無盡迴圈這樣: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屬性而言,它會被渲染器自執行,上述兩個小錯誤同樣報錯便如此
  • 儘可能用事件改變狀態 ,驅動頁面渲染重繪