拖拽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

相关推荐
西西学代码1 分钟前
Flutter---回调函数
开发语言·javascript·flutter
卷帘依旧25 分钟前
JavaScript 闭包经典问题:为什么输出 10 次 i=10
javascript
柳杉43 分钟前
Three.js × Blender:从建模到 Web 3D 的完整工作流深度解析
前端·javascript·数据可视化
reembarkation2 小时前
vue3中使用howler播放音频列表
前端·vue.js·音视频
手握风云-2 小时前
基于 Java 的网页聊天室(三)
服务器·前端·数据库
weixin199701080162 小时前
《识货商品详情页前端性能优化实战》
前端·性能优化
Forever7_2 小时前
重磅!Vue3 手势工具正式发布!免费使用!
前端·前端框架·前端工程化
用户806138166592 小时前
发布为一个 npm 包
前端·javascript
树上有只程序猿3 小时前
低代码何时能出个“秦始皇”一统天下?我是真学不动啦!
前端·后端·低代码
TT_哲哲3 小时前
小程序双模式(文件 / 照片)上传组件封装与解析
前端·javascript