拖拽API的简单应用

我们在实际开发中经常能遇见拖拽的运用场景,比如说拖拽排序、拖拽删除等,本文将以实现一个简单的课程表来进行拖拽API的简单应用,帮助大家复习一下一些基础知识。

相关拖拽事件

实现一个元素拖拽,我们只需要在HTML标签设置draggabletrue

js 复制代码
 <div class="left">
  <div  draggable="true" class="color1 item">语文</div>
  <div  draggable="true" class="color2 item">数学</div>
  <div  draggable="true" class="color3 item">英语</div>
  <div  draggable="true" class="color4 item">音乐</div>
  <div  draggable="true" class="color5 item">政治</div>
  <div  draggable="true" class="color6 item">历史</div>
  <div  draggable="true" class="color7 item">体育</div>
 </div>

我们设置了拖拽属性,在拖动的过程中我们会触发很多事件

js 复制代码
// 拖动开始
container.ondragstart = (e) => {
    console.log('start', e.target)
}

// 拖动覆盖
container.ondragover = (e) => {
    console.log('over', e.target)
}

// 拖动进入
container.ondragenter = (e) => {
    console.log('enter', e.target)
}

// 拖动结束
container.ondrop = (e) => {
    // 一般div、td是不允许有元素置于他们上面,在ondragover设置阻止冒泡
    console.log('drop', e.target)
}

如上,我们在这个应用主要用到了这几个拖拽事件,其中要特别注意的是ondrop事件,因为很多的HTML标签是不允许有其他元素覆盖在他们上面的,我们在案例中最外层用了div标签,所以必须要设置阻止冒泡才能让该事件生效

设置拖拽鼠标样式

如效果图所演示,我们在新增课程的时候,鼠标呈现的是一个加号的状态,在移除时又是一个简单的鼠标样式。这里我们是通过datasetondragstart设置相关属性来进行动态实现的

js 复制代码
    <div class="left">
        <div  data-effect="copy" draggable="true" class="color1 item">语文</div>
        <div  data-effect="copy" draggable="true" class="color2 item">数学</div>
        <div  data-effect="copy" draggable="true" class="color3 item">英语</div>
        <div  data-effect="copy" draggable="true" class="color4 item">音乐</div>
        <div  data-effect="copy" draggable="true" class="color5 item">政治</div>
        <div  data-effect="copy" draggable="true" class="color6 item">历史</div>
        <div  data-effect="copy" draggable="true" class="color7 item">体育</div>
    </div>
js 复制代码
container.ondragstart = (e) => {
    // 设置拖拽鼠标样式 默认值为move
    e.dataTransfer.effectAllowed = e.target.dataset.effect
}

设置拖拽背景色

依旧根据设置的datakey,并检索父级,通过ondragenter事件动态插入class,实现背景色的显示

js 复制代码
  <div class="left" data-drop="move">
      <div  data-effect="copy" draggable="true" class="color1 item">语文</div>
      <div  data-effect="copy" draggable="true" class="color2 item">数学</div>
      <div  data-effect="copy" draggable="true" class="color3 item">英语</div>
      <div  data-effect="copy" draggable="true" class="color4 item">音乐</div>
      <div  data-effect="copy" draggable="true" class="color5 item">政治</div>
      <div  data-effect="copy" draggable="true" class="color6 item">历史</div>
      <div  data-effect="copy" draggable="true" class="color7 item">体育</div>
 </div>


 <tr>
     <th rowspan="4" class="span">上午</th>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
     <td data-drop="copy"></td>
</tr>
js 复制代码
function getDropNode(node){
    while(node){
        if(node?.dataset?.drop){
            return node
        }
        node = node.parentNode
    }
}

function clearDropStyle(){
    const dropNodes = document.querySelectorAll('.drop-over')
    dropNodes.forEach((node) => {
        node.classList.remove('drop-over')
    })
}

container.ondragenter = (e) => {
    clearDropStyle()
    const dropNode = getDropNode(e.target)
    if(!dropNode){
        return
    }
    if( e.dataTransfer.effectAllowed === dropNode?.dataset?.drop){
        dropNode.classList.add('drop-over')
    }
}

实现新增删除

根据一开始的设想,我们是新增了dataset进行同类别的有效拖拽,依旧进行比较,根据情况新增、删除节点

js 复制代码
let source;

container.ondragstart = (e) => {
    // 设置拖拽鼠标样式
    e.dataTransfer.effectAllowed = e.target.dataset.effect
    source = e.target
}


container.ondrop = (e) => {
    // 一般div、td是不允许有元素置于他们上面,在ondragover设置组织冒泡
    console.log('drop', e.target)

    clearDropStyle()
    const dropNode = getDropNode(e.target)
    if(!dropNode){
        return
    }
    if(e.dataTransfer.effectAllowed !== dropNode.dataset.drop){
        return
    }
    if(dropNode.dataset.drop === 'copy'){
        dropNode.innerHTML = ''
        const cloned = source.cloneNode(true)
        cloned.dataset.effect = 'move'
        dropNode.appendChild(cloned)
    }else{
       source.remove()
    }
}

我们在ondrop是不能拿到拖拽的节点的,设置一个全局变量,在ondragstart中保存节点,同时在复制完节点后要将其dataset-effect改成move

相关推荐
潜意识起点12 分钟前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛16 分钟前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿26 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@3 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss7 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247559 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255029 小时前
前端常用算法集合
前端·算法