最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 面试题:如何实现一个拖拽插件(一)

    正文概述 掘金(不理不理肥嘟嘟左卫门)   2021-03-29   730

    在我的项目中使用过vue.draggable这个插件,用来做拖拽,它是封装Sortable这个插件的。

    各位大爷们,传送门我放这:

    github.com/SortableJS/…

    github.com/SortableJS/…

    我做项目没有看过其源码,说起它的原理来也是靠猜的,今天我网上去下载下源码来,看了半个小时,两眼一抹黑,更懵了。

    然后我就网上去找拖拽改变顺序的原理,万能的搜索引擎,我找到了这个大佬写的,拿来看了,方才如梦初醒。各位大爷,链接给你们放下面了。

    www.jianshu.com/p/a923add40…

    我把他的代码拷贝下来,运行了下,看了看,自己照着写了写,谢谢作者大佬。谢谢大哥精简的代码,让我明白了其实现原理。厉害,厉害,谢谢!谢谢!谢谢!

    如果有侵权,我立即删了

    虽然赶不上人家,不过,胡适说过:

    怕什么真理无穷,进一寸有一寸的欢喜。

    我之前想得很复杂,如何判断拖拽后的元素位于什么位置,如何去改变顺序,想来想去,更没有办法下笔了。各位大爷们,完整渣渣代码我贴在最后,我把我觉得核心的拿出来讲讲。还是带着问题去看吧。

    • 靠哪个属性进行拖拽?
    • 怎么判断拖拽到哪个位置了?
    • 怎么交换顺序?

    1、靠哪个属性值进行拖拽

    利用h5的拖拽属性draggable,配合相应的事件ondragstart和ondragover来实现拖拽。

    2、怎么判断拖拽到哪个位置了

    首先被拖拽的目标元素dragObj,经过每一个子元素item时候,都会触发其dragover事件。

    可以利用一个函数,来计算item在父元素的的index值。经过该元素时候,计算item和dragObj的index值,然后利用dom的insertBefore来把dragObj插入到该元素上面或者下面。

    判断index大小主要用来判断是在item的上面插入还是下面插入。

    3、怎么交换顺序

    交换顺序主要是使用了dom的insertBefore,它是插入和改变dom节点的api,各位大爷,链接我放这:

    www.w3school.com.cn/jsref/met_n…

    所以,说了那么多,那个获取index的函数怎么写?

    // 获取元素所在数组的当前index        
    function _index(el) {            
        var index = 0;           
        if (!el || !el.parentNode) {                
            return -1;          
        }            
        // 反复寻找它有几个前兄弟元素            
        // previousElementSibling 属性返回指定元素的前一个兄弟元素,循环遍历之前的所有兄弟节点           
        while (el && (el = el.previousElementSibling)) {                
            // console.log(el);                
            index++;                
            // console.log('--while---',el,index);            
        }            
        // console.log(index)            
        return index;        
    }
    

    最后,

    关键:一个属性,一个变量,两个事件,一个函数,一个dom的api。

    一个属性:draggable="true"

    一个变量:用来存放被拖拽的元素dragObj

    两个事件:ondragstart,ondragover

    一个函数:计算元素处于父元素的子元素数组里面的哪个index

    一个dom的api:insertBefore

    思路

    1、给被拖拽的子元素加上draggable="true"属性,

    2、父元素绑定ondragstart和ondragover事件,

    3、dragstart的时候,把被拖拽的元素赋值存起来为dragObj,

    4、每个被经过的子元素target都会有dragover事件,

    5、在dragover事件里,利用获取index的函数,判断被拖拽元素dragObj和target元素的index的大小

    6、在taget的nextSibing或者taget自己利用insertBefore插入dragObj。

    最后:

    这个版本是乞丐版本,各位大爷们将就下哈。我后续还会接着啃vue.draggable源码,给各位看官用口水话讲出来,方便理解,我还会继续更新拖拽方面的内容,这只是一个开始。

    面试题:如何实现一个拖拽插件(一)

    最后渣渣代码:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .item {
                width: 100%;
                height: 50px;
                border: 1px solid red;
            }
        </style>
    </head>
    
    <body>
        <div id="ordered-container"> </div>
        <script>            
            var data = [
            { label: "Item 1" }, 
            { label: "Item 2" }, 
            { label: "Item 3" }, 
            { label: "Item 4" }, 
            { label: "Item 5" }, 
            { label: "Item 6" }]
    
            setupOrderedContainers();
    
            function setupOrderedContainers() {            
                // 先渲染列表            
                var container = document.querySelector("#ordered-container");            
                var html = '';            
                data.forEach(item => {               
                    html+=`<div class="item" draggable="true">                            
                        ${item.label}                        
                        </div>`;           
                })            
                container.innerHTML = html;            
                var drag = null;            
                // 拖拽开始,赋值            
                container.ondragstart = function (event) {                
                    drag = event.target;           
                }            
                // 拖拽过程中,插入元素            
                container.ondragover = function (event) {                
                    var target = event.target;                
                    // console.log('--ondragover---', _index(drag), _index(target))                
                    if(_index(drag) < _index(target)) { 
                        // 向下拖拽                   
                        // console.log('向下拖拽');                    
                        target.parentNode.insertBefore(drag, target.nextSibing);                
                    } else {                    
                        // console.log('向上拖拽');                    
                        target.parentNode.insertBefore(drag, target);                
                    }            
                }                   
            }  
    
            // 获取元素所在数组的当前index        
            function _index(el) {            
                var index = 0;           
                if (!el || !el.parentNode) {                
                    return -1;          
                }            
                // 反复寻找它有几个前兄弟元素            
                // previousElementSibling 属性返回指定元素的前一个兄弟元素,循环遍历之前的所有兄弟节点           
                while (el && (el = el.previousElementSibling)) {                
                    // console.log(el);                
                    index++;                
                    // console.log('--while---',el,index);            
                }            
                // console.log(index)            
                return index;        
            }        
        </script>
    </body>
    
    </html>
    

    起源地下载网 » 面试题:如何实现一个拖拽插件(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元