2017-08-06 188 views
3

每次修改用於呈現v-for列表的數組時,我都會遇到此問題。VueJS v-對於不想要的行爲

比方說,我有三個項目的V型的列表:

<ul> 
    <li v-for="item in items"></li> 
<ul></ul> 

<ul> 
    <li>One</li> <!-- Has focus or a specific child component --> 
    <li>Two</li> 
    <li>Three</li> 
</ul> 

添加一個新的項目,以項目數組:

<ul> 
    <li>New Item</li> <!-- Focuses on this item, the child component seems to be moved here --> 
    <li>One</li> 
    <li>Two</li> 
    <li>Three</li> 
</ul> 

的重點似乎移動...

請看看說明該問題https://jsfiddle.net/gu9wyctr/

我明白了個小提琴在這一點上必須有一個很好的理由,但我需要管理它或完全避免。想法?

編輯:

我剛剛意識到,我的解釋是比較模糊的。這裏有一個更新的小提琴來說明問題https://jsfiddle.net/keligijus/d1s4mjj7/

的問題是,輸入的文本被移動到另一個元素...

我的現實生活中的例子。我有一個類似論壇的帖子列表。每個帖子都有一個回覆的輸入。如果某人在其他用戶輸入回覆時發佈了新帖子,則該用戶輸入的內容將被移至另一帖子。就像小提琴中的例子。

+0

有你嘗試使用vues refs而不是Dom選擇器?這些參考文獻應相應更新,並始終給予您正確的參考。當你在vue中使用Dom選擇器或jQuery時,你應該已經假定你正在做的事是一個不好的習慣。 –

回答

3

提供密鑰就是答案!

https://vuejs.org/v2/guide/list.html#key

當Vue公司正在更新與V-用於渲染的元素的列表,它默認使用「就地補丁」的策略。如果數據項的順序發生了變化,Vue不會移動DOM元素來匹配項目的順序,而只是簡單地修補每個元素,並確保它反映應該在該特定索引處呈現的內容。這與Vue 1.x中track-by =「$ index」的行爲類似。

此默認模式是有效的,但只適用於您的列表呈現輸出不依賴子組件狀態或臨時DOM狀態(例如表單輸入值)的情況。

爲了給Vue一個提示,以便它可以跟蹤每個節點的身份,從而重用和重新排序現有元素,您需要爲每個項目提供唯一的鍵屬性。對於關鍵的理想值將是每個項目的唯一ID。這個特殊的屬性大致相當於1中的track-by。X,但它就像一個屬性,所以你需要使用V-綁定將其綁定到動態值(使用速記這裏):

<li v-for="(item, index) in items" :key="'item-'+item"> 
    <input :id="'item-'+index" type="text" style="width:80%;"> 
</li> 

更新小提琴表明該工程https://jsfiddle.net/keligijus/d1s4mjj7/3/

1

試試這個:

var app = new Vue({ 
 
    el: '#app', 
 
    data: { 
 
    messages: [ 
 
     { message: 'Hello Vue!', id: 0 }, 
 
     { message: 'Hello Vuex!', id: 1 }, 
 
     { message: 'Hello VueRouter!', id: 2 } 
 
    ], 
 
    msg: null, 
 
    focus: 'item-1' 
 
    }, 
 
    mounted() { 
 
    \t document.getElementById(this.focus).focus() 
 
    \t setTimeout(() => { 
 
    \t this.messages.unshift({ message: 'Focus moves!', id: 3 }) 
 
    }, 2000) 
 
    \t setTimeout(() => { 
 
    \t this.messages.unshift({ message: 'Moves again...', id: 4 }) 
 
     this.msg = `I suppose this happens because of the way DOM is updated and I understand there must a good reason for this. However I need to avoid this behaviour. How can I do this?` 
 
    }, 4000) 
 
    }, 
 
    updated: function() { 
 
    \t document.getElementById(this.focus).focus() 
 
    } 
 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script> 
 
<div id="app"> 
 
    <ul> 
 
    <li v-for="(message, index) in messages"> 
 
     <input :id="'item-'+message.id" type="text" v-model="message.message" style="width:80%;"> 
 
    </li> 
 
    <li v-if="msg">{{msg}}</li> 
 
    </ul> 
 
</div>

基本上我做ID即使添加新項目一樣,然後我可以跟蹤關注項目,並集中他們再次更新後還是一樣。

+0

謝謝Chazeon,不過這是一種拙劣的方式。它可能對一個非常簡單的例子很有用,但在現實生活中,這種解決方案是不可行的。 我需要深究這一點。 – keligijus