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

相关推荐
吕彬-前端5 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱8 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai17 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨18 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端