1. 程式人生 > >Vue 父元件迴圈使用refs呼叫子元件方法出現undefined的問題

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元件每次改變的只有資料。從這個角度思考,我的設計是不合理的。