拖拽组件是HTML常用的操作,尤其在当前高交互的时代,鼠标单击已经不能满足甲方老爹的需求。除了点来点去的,还要拖来拖去。
常用属性
HTML 拖拽选包含的操作
| 属性 | 说明 |
|---|---|
| draggable | 值是true,默认为false是开启一个拖拽的关键 |
| ondragstart | 拖拽元素起始会调用 |
| ondrag | 元素发生拖拽,只要拖拽元素离开原本位置会一直调用 |
| ondragleave | 元素完全离开原来的位置开始调用 |
| ondragenter | 元素开始进入目标区域 |
| ondragover | 元素被拖拽到目标区域上方 |
| ondrop | 元素落在目标元素上方时调用 |
| ondragend | 元素还未到达目标区域,就点击Esc案件或者鼠标释放调用 |
| ondragexit | 没有找到可支持的情况,暂时可以忽略 |
执行时间顺序
这里简单绘制下拖拽事件时间图
drag 会在dragstart 开始的时伴随整个托拽过程一直执行
dragend比较特殊,但看字面意思似乎会题解错误,在chrome浏览器测试得知,这其实是一种退出操作,也就是只有在未完成托拽、未到达目标元素时才会调用。
dropend 会在以下列举的情况下调用
- 会在
dragstart、ondragleave、ondragenter阶段释放鼠标的时候调用 - 任意阶段摁下键盘
Esc键 - 进入
dragover但是又离开,然后释放了鼠标 - 其它意外操作
托拽事件
所有事件是有个继承关系,从上图可以看到托拽事件是继承于鼠标事件的,而且很多时候鼠标事件的执行优先于托拽事件,这就需要在特定时刻阻止默认的事件。例如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 多了 “允许” 这两个关键字。尝试了几次,这个操作究竟会产生什么视觉效果,看下图就明白了。只会对鼠标右下角的小框框的右下角有影响,我这里也没搞明白用途。

setData和getData用来存储和读取一些数据,一般在源元素存储,在目标元素读取。但是这两个元素只能存取一些字符串,复杂对象直接转成字符串了,也不太好。建议自己封装代替。
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");
}