xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

提升拖动排序的效率 #23

Open xinglie opened 8 years ago

xinglie commented 8 years ago

拖动排序在前端是最常见的功能之一,那么如何做到效率最优呢?

从拖动上,我们一般是为要拖动的元素绑定onmousedown事件,在onmousedown中进行判断是否需要拖动,如果可以拖动,则给document绑定onmousemove和onmouseup事件,在onmousemove中进行位置更改,onmouseup中释放拖动

通常我们拖动时,需要实时获取鼠标指向的DOM节点,在onmousemove中根据event.srcElement或event.target获取,这样才能更改拖动中的各种效率,比如树节点的拖动,来显示是插入到2个节点中间,还是追加到某个节点下,在onmousemove中需要注意的时,拖动的东西不能挡着鼠标,要不然通过event.target或srcElement获取到的始终是挡着鼠标的节点,因此我们可以把拖动提示的节点跟随在鼠标的旁边,而不是挡在鼠标下面

对于鼠标拖动到浏览器外边浏览器还能响应onmousemove事件,我们通常需要判断节点有没有setCapture方法,如果有则调用一下setCapture,这样对于像IE6这样的浏览器鼠标在浏览器外面也是可以响应的,但是这样又引入一个新问题,从firefox 4开始,firefox也提供了setCapture方法,一但这个方法被调用,在onmousemove事件中,取event.target始终是设置setCapture的这个节点,不再是鼠标指向的节点,不管有没有节点挡着鼠标,所以到这个地方又需要判断浏览器,我是不喜欢浏览器判断然后写不同的代码的,尽量使用各浏览器间通用的方法

找到一个各浏览器间还算统一的方法document.elementFromPoint方法,不过这个方法在safari 4.0 ,opera 10.10实现都是不正确的,不过随后的版本修正了这个问题,但是这个方法还是有细微的浏览器差别,用起来也不是让人省心,而且在iOS5跟之前的iOS4也是不一致的,关于iOS的这里有篇文章可供参考:http://www.icab.de/blog/2011/10/17/elementfrompoint-under-ios-5/

目前可通过如果元素有setCapture方法就使用elementFromPoint方法,否则使用onmousemove中的event.target或event.srcElement

对于获取到鼠标指向的元素后,可缓存下来,鼠标再次移动时,先判断鼠标是否仍处于缓存的元素内,如果处于缓存的元素内,无需获取鼠标下的节点,反之再次获取鼠标下的节点,尽可能的提升查询效率。