手动js实现一个拖拽删除的功能

in 前端javascript with 0 comment

手动实现一个拖拽删除的功能

preview

首先我们来准备要删除的dom元素和承接删除元素的箱子trash,我们的代码如下:

<ul>
    <li draggable="true">drag me 1</li>
    <li draggable="true">drag me 2</li>
    <li draggable="true">drag me 3</li>
    <li draggable="true">drag me 4</li>
    <li draggable="true">drag me 5</li>
    <li draggable="true">drag me 6</li>
    <li draggable="true">drag me 7</li>
    <li draggable="true">drag me 8</li>
</ul>
<div id="trash"></div>

可拖动的元素都要设置 draggable='true'

可拖动元素的事件主要用到 dragstart, dragover, dragend,这里的trash div主要用到事件有dragenter,dragover,drap

let lis = [].slice.call(document.getElementsByTagName('li'))
const elTrash = document.getElementById('trash')
let cloneTarget // 克隆节点
let ableResume = true
lis.forEach(item => {
    item._pos = item.getBoundingClientRect()
    item.addEventListener('dragstart', e => {
        const currentDragEl = e.target
        const { screenX, screenY } = e
        currentDragEl._pos.gapX = screenX - currentDragEl._pos.x
        currentDragEl._pos.gapY = screenY - currentDragEl._pos.y
        e.dataTransfer.setData('idx', lis.indexOf(e.target))
        cloneTarget = currentDragEl.cloneNode(true) // 克隆一个节点作为占位

        currentDragEl.style.position = 'absolute'
        currentDragEl.parentNode.insertBefore(cloneTarget, currentDragEl.nextSibling) // 插入刚刚克隆的节点
    })
    item.addEventListener('dragover', e => {
        const currentDragEl = e.target
        currentDragEl.style.top = '-1000px' // 把拖拽的节点移到屏幕外看不到的地方
        cloneTarget.style.opacity = '0'
    })
    item.addEventListener('dragend', e => {
        if (ableResume) { // 判断是否恢复节点的位置
            const currentDragEl = e.target
            currentDragEl.removeAttribute('style')
            cloneTarget.parentNode.insertBefore(currentDragEl, cloneTarget)
        }
        cloneTarget.parentNode.removeChild(cloneTarget)
        ableResume = true
    })
})
elTrash.addEventListener('dragover', e => {
    e.preventDefault() // 触发 drop 事件必须先在 dragover 里面取消默认事件
})
elTrash.addEventListener('drop', e => {
    e.preventDefault() // 避免将文件拖入时,文件做为链接打开了,我们这里是DOM元素,不会出现你这个问题
    const idx = e.dataTransfer.getData('idx')
    const el = lis[idx]
    lis.splice(idx, 1) // 更新下list
    ableResume = false
    el.removeAttribute('style')
    el.removeAttribute('draggable')
    elTrash.appendChild(el)
})

现在我们可以通过拖拽li将它放进到垃圾桶里,并有相应的拖拽和占位效果

OK,简单的拖拽功能就实现啦

Responses