Vue拼接(将数组项移动到数组中的另一个位置)不更新DOM

Posted

技术标签:

【中文标题】Vue拼接(将数组项移动到数组中的另一个位置)不更新DOM【英文标题】:Vue splice (Move array item to another location in array) not updating the DOM 【发布时间】:2020-03-15 15:16:22 【问题描述】:

我正在尝试将数组中的一项移动到位置x 到位置2。下面的代码工作并将项目移动到新位置。但是,vue 不会更新DOM

这是我正在使用的代码:

export default class LayersPanel extends Vue 
  @ProvideReactive() public layers: any[] = [
     name: 'Layer 1' ,  name: 'Layer 2' ,  name: 'Layer 3' ,  name: 'Layer 4' 
  ]
  public onDragDrop(evt: DragEvent) 
    let offset = parseInt(evt.dataTransfer.getData('text/plain'))
    this.layers.splice(2, 0, this.layers.splice(offset, 1)[0])
  

<template>
  <div class="layers-panel" @dragover="onDragOver" @drop="onDragDrop">
    <layer v-for="(layer, index) in layers" :key="index" :info="layer" :offset="index"></layer>
  </div>
</template>

我不确定这是否与this note in the docs 有关:

当您通过直接设置索引(例如 arr[0] = val)或修改其长度属性来修改数组时。同样,Vue.js 也无法获取这些更改。始终使用 Array 实例方法或完全替换它来修改数组。 Vue 提供了一个方便的方法 arr.$set(index, value),它是 arr.splice(index, 1, value) 的语法糖。

据说.splice() 是一种变异方法,所以我认为这无关紧要。我在这里做错了什么?

【问题讨论】:

layers 很可能没有反应。它是否在您的data 中定义? 我正在使用带有装饰器的打字稿:@ProvideReactive() public layers: any[] = [ name: 'Layer 1' , name: 'Layer 2' , name: 'Layer 3' , name: 'Layer 4' ] 这听起来像是v-for 中的key 属性的问题。不看模板代码很难说。您可能想尝试在您的v-for 中使用 name 转储层名称。我怀疑您使用的有状态组件对更改没有反应,但 name 应该显示最新值。 【参考方案1】:

问题的来源可能是您选择的key

<layer v-for="(layer, index) in layers" :key="index" :info="layer" :offset="index"></layer>

最初&lt;layer&gt; 组件将具有键0123,分别对应于层Layer 1Layer 4

如果您随后将位置 0 的图层移动到位置 2,那么您现在将按照 Layer 2Layer 3Layer 1Layer 4 的顺序拥有它们。但是,键是由索引决定的,所以 Layer 2 现在的键值为 0

当 Vue 在重新渲染后尝试配对组件时,它会使用键。所以&lt;layer&gt;key0 过去对应于Layer 1,但现在它将对应于Layer 2

这不一定是个问题。 Layer 4 很简单:它没有移动,所以它不会改变。其他三个已经移动,但他们的 info 属性应该会相应更新。

这就是有状态组件的问题所在。虽然前三个组件的 info 属性会更新,但不一定会对任何其他内部状态产生任何影响,例如 data 属性所持有的状态.这些仍将保留原始 info 值的值。

这里的解决方案通常是为key 使用更合适的值。从问题中不清楚您的情况可能是什么值。在某些情况下,您可能需要在每个数组项中添加一个额外的属性,以便为其提供合适的属性。

重要的是键是不同的并且与数组项相关联。如果图层的 name 是唯一标识符,那么您可以使用它,例如:key="layer.name".

【讨论】:

好吧,酷!什么时候适合使用索引作为键? @GetOffMyLawn key 需要唯一标识从一次渲染到下一次渲染的等效 VNode(转换为组件和元素)。等效组件将被更新,而没有合适等效组件的组件将被相应地销毁或创建。理解这一点非常重要:根据我的经验,大多数使用 Vue 的开发人员不知道 key 做了什么,并试图通过像 'never use index' 这样的过度简化来蒙混过关。如果您了解 key 的作用,那么确定特定的值选择是否合适应该相对容易。

以上是关于Vue拼接(将数组项移动到数组中的另一个位置)不更新DOM的主要内容,如果未能解决你的问题,请参考以下文章

将元素移动到数组中的第一个位置

如何在更改`UICollectionViewCell`位置时正确移动数组项

数组常用的几种方法

数组常用的方法和返回值

数组常用的几种方法

如何将 MKCircleView 的一个位置移动到 MKMapView 中的另一个位置?