sortable.js——Vue 数据更新问题

从一个 bug 提及

在一个需求中,我须要实现一个拖拽的功能,其中我使用了 sortable.js 去实现,但我发现我拖拽以后的数据并无渲染在页面上。html

简而言之,举个例子,原先的数组是 [1,2,3,4],拖拽以后,变成了 [4,1,2,3],但在视图上并无显现,这不经让我迷惑不解,开始了如下问题的探索,在此记录一下前端

Vue 的数组更新问题

看到以上问题,你确定会认为我处理数组的方式不对,毕竟官方文档明确指出了数组的几个坑vue

如下参考 Vue 文档 因为 JavaScript 的限制,Vue 不能检测如下数组的变更: 1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue 2.当你修改数组的长度时,例如:vm.items.length = newLengthreact

可是实际上,我避开了这个坑,实际的实现是经过 splice 实现的,这样其实是不会有问题的。git

const tempItem = me.tabs.splice(e.oldIndex, 1)[0]
me.tabs.splice(e.newIndex, 0, tempItem)
复制代码

题外话 实际上,咱们在 Vue 的数组书使用 splicepush等方法,Vue 都已经作了一层封装,因此它们才能出发视图更新,若是有想更加深刻了解,能够阅读源码github

Vue 强制刷新——$forceUpdate()

对于这一点,尤大大表示,通常而言,咱们都不须要用到的,若是须要用到的话,99.9%的状况,是自身的问题。segmentfault

$forceUpdate() 的功能,就是迫使实例从新渲染,但尴尬的是,我使用了以后并无效果,我以为是我用错了,O__O "…数组

相似的代码以下:bash

// 在控制变量改变的时候进行 强制渲染更新

let childrenRefs = this.$refs.elTabs.$children
this.$nextTick(() => {
  childrenRefs.forEach(child => child.$forceUpdate())
})
复制代码

参考:www.imooc.com/wenda/detai…ui

最后的解决方法

其实对于最后的解决方法,来源于 segmentfault,我仍是心存疑问的,废话少说,咱们来看代码

先用一个数据深拷贝数据,这里使用了 slice 方法,而后置空,最后在 $nextTick 中赋值深拷贝出来的数组值。最后能够了。

我猜想有两个,数组的长度不变,只是数组的长度变化, Vue检测不到,对于这个猜测,很容易就被本身推翻了,毕竟试了一下,并不会这样的。

那就多是 sortable.js 的问题了

// 代码参考:https://segmentfault.com/q/1010000009672767
mounted : function () {
  var that = this;
  var sortable1 = new Sortable(document.querySelector('#topicNumBox'), {
    sort: true,
    animation: 300,
    onEnd: function (evt) {  //拖拽结束发生该事件
      that.questionData.splice(evt.newIndex, 0, that.questionData.splice(evt.oldIndex, 1)[0]);
      var newArray = that.questionData.slice(0);
      that.questionData = [];
      that.$nextTick(function () {
        that.questionData = newArray;
      });
    },
  });
}
复制代码

结论

虽然问题解决了,可是最终的根源并无找到O__O "…

但也提供一两种很强势的刷新数据的方法,之后须要用到的时候能够试下(愿你不会用到)

欢迎你们关注个人公众号~前端大杂货铺~