一、需求背景:

               项目要求在多选的情况下对已选择的值进行手动拖动排序

二、设计分析:

               我们正常的js插件中没有此功能,需要拖动里面的元素,就需要添加在生成的已选择的li元素里添加h5属性(draggable="true"),这样我们才能有拖动元素的这个效果。然后我们在select初始化的页面再监听拖动事件。除了核心的拖动外,我们还需要注意两件事,一件事是拖动完毕后发送请求后的再次修改操作,这要求返回的值我们要按照顺序显示上去,因为使用过select相关插件的都知道,默认显示值得顺序跟下拉列表的顺序有关系,其次就是如果我们需要根据某些条件需要改变下拉框里的值,需要关注默认值是否在下拉框中,如果没有需要剔除。

三、示意图

 

java拖动排序后端怎么做的 js拖动排序_java拖动排序后端怎么做的

四、核心代码

  1. 我们需要在插件中找到生成已选择值得HTML,加上draggable="true"的属性,让元素可以拖动(这个是我使用插件源代码,在里面添加此属性)
  2. 添加拖动事件的监控,并写好监控事件的处理逻辑(代码是vue框架,只参照核心js就好了)
this.$nextTick(function () {
                //获取ul元素的节点,找到ul li的相关HTML
                var node = document.querySelector('.ciphers_ssl .select2-selection__rendered')
              
                var draging = null;
              
                //使用事件委托,将li的事件委托给ul
                node.ondragstart = function(event) {
                    //firefox设置了setData后元素才能拖动!!!!
                    event.dataTransfer.setData("te", event.target.innerText); //不能使用text,firefox会打开新tab
                    draging = event.target;
                }
                node.ondragover = function(event) {
                    event.preventDefault();
                    var target = event.target;
                    //因为dragover会发生在ul上,所以要判断是不是li
                    if (target.nodeName === "LI"&&target !== draging) {
                        if (_index(draging) < _index(target)) {
                            target.parentNode.insertBefore(draging,target.nextSibling);
                        } else {
                            target.parentNode.insertBefore(draging, target);
                        }
                    }
                }
             
                //获取元素在父元素中的index
                function _index(el) {
                    var index = 0;

                    if (!el || !el.parentNode) {
                        return -1;
                    }
                    //下面这个循环的意思是,看当前el是否有值,并且给当前el赋值上前一个el的值,直到el为null时,循环结束,每一次循环就代表在当前值得前面还有一个,也就直到当前值得序列号
                    while (el && (el = el.previousElementSibling)) {
                        index++;
                    }

                    return index;
                }
            })

至于我之前在设计分析提到的两个注意项,只需要参考我另外写的如何初始化select插件就好了,还有就是再次展示的时候,我们需要把已选择的默认值,如果下拉框有,就需要把已选择的值按照顺序放到最前面,这样在初始化的时候,才会按照正确的顺序展示