拖放操作里面非常重要的一个点就是,我们要确定哪里发生了拖放事件。顾名思义,拖放事件,就是有脱(drag)事件和放(drop)事件。
拖放操作里面非常重要的一个点就是,我们要确定哪里发生了拖放事件。顾名思义,拖放事件,就是有脱(drag)事件和放(drop)事件。
当某个元素被拖动的时候,在这个元素上将被依次触发以下事件:
dragstart
drag
dragend
按下鼠标键并开始移动鼠标时,就会在被拖动元素上触发 dragstart
事件,随机触发 drag
事件, drag
事件会在鼠标移动的过程中不断被触发,当拖动停止,无论是把元素放置到有效的目标还是无效的目标上,都会触发 dragend
事件。
tip:在元素被拖动期间,大多数浏览器会为正在被拖动的元素创建一个半透明的副本,这个副本始终随着光标移动。
当某个元素被拖动到一个有效的放置目标上,下列事件又会依次发生:
dragenter
dragover
dragleave
或 drop
只要有元素被拖动到放置目标上,就会触发 dragenter
事件,随即会触发 dragover
事件,在被拖动元素在目标元素上移动的时候会不断触发 dragover
事件,如果元素移出了目标元素就会触发 dragleave
事件,如果元素被放置到目标元素中则会触发 drop
事件。
有些元素默认是不允许放置的,当我们拖动的元素放置到无效的放置目标上,会发生什么事呢?其实也没什么事会发生,就是无论用户如何操作,都不会发生 drop
事件。
但是我们可以将它设置为可以被放置的。重写 dragenter
和 dragover
事件的默认行为就可以将目标设置为可以被放置的了。
let dropTarget = document.getElementById('target') dropTraget.addEventListener('dragenter', e => { e.preventDefault() }, false) dropTraget.addEventListener('dragover', e => { e.preventDefault() }, false)
dataTransfer
对象 现在我们把目标设置为可放置的,但是当我们把元素拖到目标上面放下的时候,依然什么事情都没有发生,这就对了
drop
事件 ,就是什么事都没有发生。
所以,我们需要实现数据的交互。这个时候,我们就要用到 dataTransfer
这个对象。 dataTransfer
是一些列拖放事件的事件对象里的一个属性( e.dataTransfer
)。
dataTransfer
主要有两个方法, getData
和 setData
。
这两个方法有什么作用呢?举个栗子:你可以在 A
元素被拖动的时候设置数据
e.dataTransfer.setData('text', 'I/'m A!!!')
然后在目标 B
的 drop
事件中可以获取到这个数据
e.dataTransfer.getData('text') // I'm A!!!
这样就可以实现拖拽元素和目标元素之间的通信了。
这两个方法使用起来要注意的问题挺多,具体的请看 文档
dropEffect
和 effectAllowed
利用 dataTransfer
的 dropEffect
和 effectAllowed
这两个属性可以控制被拖动元素做什么操作,以及放置目标元素接收什么操作。
其中, dropEffect
属性可以知道被拖动元素能够执行哪种放置行为,是把元素复制到目标元素,还是直接移动到元素…。这个属性可以被设置为以下 4 个值:
none
:不能把拖动的元素放到目标 move
:应该把拖动的元素移动到目标 copy
:应该把拖动的元素复制到目标 link
:放置目标会打开拖动的元素(拖动的元素必须是一个链接,有 URL) dropEffect 必须在 dragenter 事件中设置
effectAllowed
是和 dropEffect
协同工作的,表示允许被拖动元素的哪种 dropEffect
uninitialized
:没有给被拖动的元素设置任何放置行为 none
:被拖动元素不能有任何行为 copy
:只允许值为 copy
的 dropEffect
move
:只允许值为 move
的 dropEffect
copyLink
:只允许值为 copy/link
的 dropEffect
copyMove
:只允许值为 copy/move
的 dropEffect
linkMove
:只允许值为 link/move
的 dropEffect
all
:允许任意的 dropEffect
effectAllowed 必须在 dragstart 事件中设置
天真的我曾经以为,把 dropEffect
设置为 move
,把 effectAllowed
设置为 move
。拖动元素的时候,浏览器就会替我去操作 DOM,改变被拖动元素的位置了。而事实上,什么都不会发生,刚开始的时候很是令人费解~~~
经过我一番测试, dropEffect
和 effectAllowed
配对如果成功的话,那么 drop
事件就会被触发,否则,就不会。