2017-08-06 189 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