Vue 父元件迴圈使用refs呼叫子元件方法出現undefined的問題
Vue 父元件迴圈使用refs呼叫子元件方法出現undefined的問題
1. 背景
最近前端專案遇到一個問題,我在父元件中使用了兩個相同的子元件child,分別設定ref
為add和update。其中A元件的功能是新增,也就是說在頁面上A頁面只有一個。而update元件是放在表格裡的,表格中的每一行資料都有update元件。跟update元件並列還有一個刪除按鈕,每次刪除完都會重新獲取資料。
2.問題描述
介面第一次載入時我對錶格的元件B進行操作的時候是沒問題的,但是當我刪除某一行的資料之後再點選B元件,出現了update元件變為undefined的問題。
<el-table-column label="操作" min-width="100px"> <template slot-scope="scope"> <UpdateButton title="修改" @click.native="updateClick(scope.row)" size="mini"></UpdateButton> <DeleteButton class="resource_pause_delete_button" @click.native="ruleDelete(scope.$index, scope.row)" /> <TimeSelectDialog ref="updateTime" title="修改暫停規則"> <update-button @click.native="updateData()" size="mini"> </update-button> </TimeSelectDialog> </template> </el-table-column>
3.定位問題
因為add和update是相同的元件,所以我一開始認為是兩個元件的衝突。但是當我把add元件完全去掉之後,還是出現了undefined的問題。所以排除了add元件是干擾這個原因。
繼續猜想以為是元件渲染問題,於是我給update元件添加了nextTick和setTimeOut來讓元件渲染完成。但是這依然不起作用。
緊接著我看了下vue中關於ref的文件。
當
v-for
用於元素或元件的時候,引用資訊將是包含 DOM 節點或元件例項的陣列。關於 ref 註冊時間的重要說明:因為 ref 本身是作為渲染結果被建立的,在初始渲染的時候你不能訪問它們 - 它們還不存在!
$refs
也不是響應式的,因此你不應該試圖用它在模板中做資料繫結。
我的元件用了element-UI的el-table元件,這個元件的內部肯定是使用了v-for迴圈的。於是我就把問題定位在v-for引起的資料繫結問題。
我把update元件從el-table中拿出來,放在表格之外。此時表格行內的按鈕只是呼叫update元件,並且每次呼叫的都是同一個元件。這次問題果然解決了。
4.總結
ref
本身是作為渲染結果被建立的,這句話應該是這樣理解的。如果在迴圈中使用了包含ref的元件,那麼迴圈出來的就是ref元件渲染的結果。當資料改變需要重新迴圈的時候,因為ref並不是響應式的,這導致包含了ref元件的行就無法再被渲染出來,因此出現了undefined的問題。
反過來想,既然update元件是一個可重用的元件,那麼我們每次都讓元件渲染其實並不是一個好的實現。實際上我的頁面中的update元件每次改變的只有資料。從這個角度思考,我的設計是不合理的。