还是没记住,浏览器托拽再总结

434 阅读3分钟

拖拽组件是HTML常用的操作,尤其在当前高交互的时代,鼠标单击已经不能满足甲方老爹的需求。除了点来点去的,还要拖来拖去。

常用属性

HTML 拖拽选包含的操作

属性说明
draggable值是true,默认为false是开启一个拖拽的关键
ondragstart拖拽元素起始会调用
ondrag元素发生拖拽,只要拖拽元素离开原本位置会一直调用
ondragleave元素完全离开原来的位置开始调用
ondragenter元素开始进入目标区域
ondragover元素被拖拽到目标区域上方
ondrop元素落在目标元素上方时调用
ondragend元素还未到达目标区域,就点击Esc案件或者鼠标释放调用
ondragexit没有找到可支持的情况,暂时可以忽略

执行时间顺序

这里简单绘制下拖拽事件时间图

image-20221026154916822

drag 会在dragstart 开始的时伴随整个托拽过程一直执行

dragend比较特殊,但看字面意思似乎会题解错误,在chrome浏览器测试得知,这其实是一种退出操作,也就是只有在未完成托拽、未到达目标元素时才会调用。

dropend 会在以下列举的情况下调用

  1. 会在dragstartondragleaveondragenter阶段释放鼠标的时候调用
  2. 任意阶段摁下键盘Esc
  3. 进入 dragover但是又离开,然后释放了鼠标
  4. 其它意外操作

托拽事件

image-20221026155807769

所有事件是有个继承关系,从上图可以看到托拽事件是继承于鼠标事件的,而且很多时候鼠标事件的执行优先于托拽事件,这就需要在特定时刻阻止默认的事件。例如ondragover这个事件在执行的时候,需要组织下默认事件,当鼠标移入目标元素时,有可能执行了mouseover的动作。同理drop也需要阻止默认事件

// dragover 拖拽到达目标元素上方
function dragover(ev) {
  ev.preventDefault();// 阻止默认事件
}

DataTransfer

DataTransfer对象用于保存拖动并放下(drag and drop)过程中的数据,在托拽事件当中可以调用。

function dragstart(ev: DragEventInit) {
  ev.dataTransfer!.dropEffect = "move"
  ev.dataTransfer!.effectAllowed = "move"
  ev.dataTransfer?.setData("__EL__", "id");
  console.log("dragstart");
}

具体Api可参考文档

developer.mozilla.org/zh-CN/docs/…

dropEffect 表示拖放操作的视觉效果

effectAllowed 用来指定当元素被拖放式所允许的视觉效果

两者的区别:从概念中理解,effectAllowed 比 dropEffect 多了 “允许” 这两个关键字。尝试了几次,这个操作究竟会产生什么视觉效果,看下图就明白了。只会对鼠标右下角的小框框的右下角有影响,我这里也没搞明白用途。

image-20221026170258775

setDatagetData用来存储和读取一些数据,一般在源元素存储,在目标元素读取。但是这两个元素只能存取一些字符串,复杂对象直接转成字符串了,也不太好。建议自己封装代替。

function dragstart(ev: DragEventInit) {
  ev.dataTransfer?.setData("__EL__", unref(dragEl).children);
}

function drop(ev) {
  ev.preventDefault();
  ev.dataTransfer?.getData("el") // 存储的html,直接准换成了一个类似 '[object HTMLDivElement]'字符串,不是很准确,无法读取原对象
  console.log("drop");
}