Vue - 从数组中拼接定位元素会将其偏移量应用于下一个索引

Vue - splicing a positioned element from an array will apply its offset to next index

我是 Vue 的新手,一直在做一个在屏幕上使用大量定位对象的小项目。我发现从我的模型中切出一个索引会导致它的定位被应用到下一个索引,重置它自己。

下面的例子是相关的(展示了类似的意外行为),但不完全是我的问题 - 转移到下一个索引的偏移量。

new Vue({
  el: '#app',
  data: {
    items: [0, 1, 2, 3]
  },
  methods: {
    take: function(i) {
      var item = $(i.target).closest('.sort').index();
      this.items.splice(item, 1);
    }
  }
});
button {
  position: relative;
  bottom: 0;
  margin-top: 25px;
}
.sort {
  padding: 15px;
  margin: 5px;
  display: inline-block;
  background: grey;
  position: relative;
}
.sort:nth-child(1) {
  top: 54px;
  left: 140px;
}
.sort:nth-child(2) {
  top: 155px;
  left: 230px;
}
.sort:nth-child(3) {
  top: 226px;
  left: 32px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="app">
  <div class="sort" v-for="item in items">
    {{ item }}

    <span class="remove" v-on:click="take">x</span>
  </div>
</div>

预期的行为是项目保持原样,直到它们自己被删除。我目前的解决方案是复制下一个索引的样式并再次应用它们。任何帮助将不胜感激,谢谢!

当您 spliceitems 中取出一个项目时,它将从 DOM 绑定数组中删除。因为您正在使用 nth-child(1)nth-child(3),所以 位置被移动 ,因为删除的元素会将剩余的元素向上移动。

所以我有一些建议给你:

  1. 鉴于每个元素的位置都是特定的,所以为什么不把它放在数据中,例如 {item: 0, class: 'zero'} - 并且标记有变化:

    <div v-bind:class="['sort', item.class]" v-for="item in items">
         {{ item.item }} <span class="remove" v-on:click="take(item)">x</span>
    </div>
    
  2. 与其像您所做的那样计算 index,不如将 item 作为参数传递,因为如果您应用 ordering/filtering,索引可能会有所不同。

  3. 位置仍然不正确 - 最好将 app 保持为 relative 并将 absolute 应用于所有 sort 类.

参见下面的演示:

new Vue({
  el: '#app',
  data: {
    items: [{
      item: 0,
      class: 'zero'
    }, {
      item: 1,
      class: 'one'
    }, {
      item: 2,
      class: 'two'
    }, {
      item: 3,
      class: 'three'
    }]
  },
  methods: {
    take: function(item) {
      this.items.splice(this.items.indexOf(item), 1);
    }
  }
});
button {
  position: relative;
  bottom: 0;
  margin-top: 25px;
}
#app {
  position: relative;
}
.sort {
  padding: 15px;
  margin: 5px;
  display: inline-block;
  background: grey;
  position: absolute;
}
.remove {
  cursor: pointer;
}
.sort.zero {
  top: 54px;
  left: 140px;
}
.sort.one {
  top: 155px;
  left: 230px;
}
.sort.two {
  top: 226px;
  left: 32px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="app">
  <div v-bind:class="['sort', item.class]" v-for="item in items">
    {{ item.item }} <span class="remove" v-on:click="take(item)">x</span>
  </div>
</div>