Vue.js 与 Sortable.js 冲突的问题

项目介绍

Vue.js 一个前端框架, 地址: https://github.com/vuejs/vue
Sortable.js 一个用于拖拽的JS插件,地址: https://github.com/RubaXa/Sortable

项目使用细节

本省Vue单纯的支持列表什么的是没有毛病的,比如下面的代码例子,运行截图就不了,这里都是手写的伪代码而已,或许根本跑不起来

  1. Vue JS

    let app = new Vue({
        el: '#app',
        data: {
            list: [
                { id: "A_1", text: "A1" },
                { id: "A_2", text: "A2" }
            ]
        },
        methods: {
            updateListSort: function (newSort) {
                //...sort....假设这里你完成了排序
                let newSortList = [];
                this.list = newSortList;
            }
        }
    })
  2. Vue HTML

    <div id="app">
        <div id="Group1">
            <div v-for="item in list" :data-id="item.id" class="d-hander">
                <span>{{item.text}}</span>
            </div>
        </div>
    </div>
  3. Sortable 代码部分

    let el = document.getElementById('Group1');
    let sortable = Sortable.create(el, {
        group: "GroupName",
        handle: ".d-hande",
        draggable: ".d-hande",
        dataIdAttr: "data-id",
        onUpdate: function () {
            let sortArray = sortable.toArray();
            app.updateListSort(sortArray);
        }
    });

出现的问题及解决

从上面的代码看起来,几乎找不到太大的问题,预想中的就是这样一定会完成,实际情况并没有那么美好。

  • 出现的问题:
    1. 如果去掉更新事件,看起来很正常,但是Vue的数组不会更新,这里是由于这个拖拽插件不支持Vue.js导致的
    2. 如果设置更新,则会发现拖拽的时候有一定的几率出现更新不成功,而且这个几率很大,甚至有时候更新是错误的,导致列表混乱。这就很严重了。
  • 解决方案
    1. 换一个插件,其他插件怎么样不太懂,JS用得少,更何况Vue这个,所以不现实。即使换了也不一定有效。
    2. 调整更新逻辑,方案只有这一个,至于怎么更新列表,尝试就比较多了。

列表更新的尝试

  1. 拖住对象销毁法
    这个方案不靠谱,起源在于列表更新异常在于两者之间的冲突导致,而实际上是由于Vue之间维护Dom对象导致的问题,如果需要具体知道为什么,可以去翻看Vue相关的源码,总能找到些内容,所以针对这个排序插件的销毁几乎起不到作用,反而导致事情的复杂化。

  2. 列表对象销毁法
    这里方案就比较靠谱了,不管排序的对象,我拿到新的排序后将现有的列表直接销毁,然后在下一阶段重建排序列表,这样即使有冲突也不存在相关问题了,可以说完美解决。只是性能如何就不得而知了,当然我并没有那么在乎这个性能的问题。毕竟不是在APP上的开发。

改进的Vue代码

var app = new Vue({
    el: '#app',
    data: {
        list: [
            { id: "A_1", text: "A1" },
            { id: "A_2", text: "A2" }
        ]
    },
    methods: {
        updateListSort: function (newSort) {
            //...sort....假设这里你完成了排序
            let newSortList = [];

            //deepClone,否则拖拽会变回去
            newSortList = utils.deepClone(newSortList);

            // Clear 现有对象列表
            this.list = [];

            this.$nextTick(() => {
                //Done
                this.list = newSortList;
            });
        }
    }
})

最后的最后

回想看看,实际的解决方案都是很简单的,只是开开始的时候想了很多稀奇古怪的招式,导致整个过程变得很复杂和艰难。实际上这是第二次遇到这个问题,最终解决了,虽然不是那么完美。

一条评论在“Vue.js 与 Sortable.js 冲突的问题”

写下你最简单的想法