拖拽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 小时前
如何结合使用thread-loader和cache-loader以获得最佳效果?
前端
垣宇1 小时前
Vite 和 Webpack 的区别和选择
前端·webpack·node.js
java1234_小锋1 小时前
一周学会Flask3 Python Web开发-客户端状态信息Cookie以及加密
前端·python·flask·flask3
化作繁星1 小时前
如何在 React 中测试高阶组件?
前端·javascript·react.js
Au_ust1 小时前
千峰React:函数组件使用(2)
前端·javascript·react.js
爱吃南瓜的北瓜1 小时前
npm install 卡在“sill idealTree buildDeps“
前端·npm·node.js
TTc_1 小时前
记录首次安装远古时代所需的运行环境成功npm install --save-dev node-sass
前端·npm·sass
翻滚吧键盘2 小时前
npm使用了代理,但是代理软件已经关闭导致创建失败
前端·npm·node.js
烂蜻蜓2 小时前
Uniapp 设计思路全分享
前端·css·vue.js·uni-app·html
GAMESLI-GIS2 小时前
【WebGL】fbo双pass案例
前端·javascript·webgl