Vue.js 当我操作dom时,v-for不再与反应数组保持同步

Vue.js 当我操作dom时,v-for不再与反应数组保持同步,vue.js,vuejs2,Vue.js,Vuejs2,这很令人困惑,我甚至认为这里有一个bug 如果您将第一个列表项动物拖动到最后一个列表项臂带以使用Sortable.js进行交换,您将看到该列表是反应性的-您可以在输出中看到它-它更新了其位置,但v-for循环没有正确反应 它会以某种方式做出反应,但不正确,因为你会看到它错误地将臂章放在第二个位置。现在,如果我直接使用Sortable.js,交换就可以了,即如果我不处理onUpdate事件,只需将其注释掉即可。我知道我可以使用VUE.draggable或其他任何名称,它维护一个内部列表,但由于各种

这很令人困惑,我甚至认为这里有一个bug

如果您将第一个列表项动物拖动到最后一个列表项臂带以使用Sortable.js进行交换,您将看到该列表是反应性的-您可以在输出中看到它-它更新了其位置,但v-for循环没有正确反应

它会以某种方式做出反应,但不正确,因为你会看到它错误地将臂章放在第二个位置。现在,如果我直接使用Sortable.js,交换就可以了,即如果我不处理onUpdate事件,只需将其注释掉即可。我知道我可以使用VUE.draggable或其他任何名称,它维护一个内部列表,但由于各种更复杂的原因,我无法使用该库。我想使用上述技术的用例在这里是不相关的——我只想知道为什么这种非常特殊的方法对于v-for是失败的


我知道这与Sortable.js自己进行DOM操作有关,但我认为一旦列表数组发生变化,v-for循环应该做出适当的反应-但它似乎被DOM中当前的内容弄糊涂了。

我认为这不起作用的原因很简单,因为我直接通过Sortable.js操作DOM,但当涉及到更新vue管理的虚拟DOM时,它不知道已经发生的dom操作,并且在反应列表更改时不会正确地更新虚拟dom,从而更新真实dom

这可能被视为vue方面的一个bug——我希望v-for循环能够反映反应列表。但这也可能被视为一种限制。这是一个折衷方案-vuejs由于性能原因不能检查真实dom和虚拟dom吗

所以为了解决这个问题,我可能需要

要实现拖放操作并通过Sortable.js直接操作dom, 然后在dom中检查新订单,并在新订单上做笔记, 然后反转dom操作, 然后用我做的笔记更新反应列表, 这将反过来更新虚拟dom。 因此,我的示例代码中缺少的步骤是反转dom操作的代码


无论如何-这就是我对上面代码不起作用的理解。

我的意思是你可以创建一个与当前列表完全相同的副本,然后让所有的名称交换。我不确定为什么你使用forEach会使它变得过于复杂,因为updateList函数传递一个oldIndex和newIndex


你能不能制作一个重复的数组并处理它?改变你正在使用的数组通常不是一个好主意。我已经尝试过了,这没有什么区别。无论如何,通过splice更新阵列是完全正确的。它正在反应性地更改阵列。。。虚拟dom不能正确呈现新的顺序。
updateList(containerDom) {
  return () => {
    Array.from(containerDom.querySelectorAll(".list-group-item")).forEach((domItem, idx) => {
      let listItemIndex = this.list.findIndex(listItem => listItem.name === domItem.innerText)
      let listItem = this.list[listItemIndex]
      listItem.pos = idx
      this.list.splice(listItemIndex, 1, listItem)
    })
  }
}
  data() {
     let list = [
        { name: "animal", pos: 0 },
        { name: "aloe", pos: 1 },
        { name: "arm", pos: 2 },
        { name: "arsenal", pos: 3 },
        { name: "antenna", pos: 4 },
        { name: "antler", pos: 5 },
        { name: "armband", pos: 6 },
      ]
    return {
      original_list: JSON.parse(JSON.stringify(list)),
      list: list,
    };    
  },

  methods: {
    listToJSON(list) {
      return JSON.stringify(list, null, 2)
    },
    updateList(context) {
      let old = context.oldIndex
      let $new = context.newIndex
      let temp_name = this.original_list[old].name
      this.original_list[old].name = this.original_list[$new].name
      this.original_list[$new].name = temp_name
    }
  },