1. 需求
做一个视频投屏墙的弹窗,弹窗可以拖拽,里面的视频也要可以拖拽调换顺序,项目是vue的
2. 基础代码结构
<!-- 使用了vue-draggable-resizable 插件作为弹窗主题可拖拽的部分 -->
<vue-draggable-resizable
:resizable="false"
:draggable="true"
@dragging="containerDragging"
:w="960"
v-show="videosscreenshow"
class="videosPopover"
style="border: none"
>
<!-- 头部 -->
<div class="header"></div>
<!-- 主体部分,也就是视频墙 -->
<div v-for="videoGridItem in item.gridIndex" draggable="true" @dragstart="videoDragstart" @dragend="videoDragend" @drop="videoDragenter" @dragover="dragover" :id="['videogrid_'+videosGroupValue+'_'+item.gridIndex+'_'+videoGridItem]" class="js_videogrid">
<div class="deleteVideo" title="删除" @click="delVideo('video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem)">x</div>
<video class="js-media" name="videoElement" :id="['video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem]" autoplay >
<p>你的浏览器不支持 HTML5 Video。</p>
</video>
</div>
</vue-draggable-resizable>
3. 出现的第一个问题
主体部分我是用draggable="true"实现的,当拖动里面的视频块的时候,整个弹窗会跟着动,这个问题比较明显,就是没有阻止子元素的拖拽事件冒泡,稍作修改,加上stop指令阻止冒泡:
<div v-for="videoGridItem in item.gridIndex" draggable="true" @dragstart.stop="videoDragstart" @dragend.stop="videoDragend" @drop.stop="videoDragenter" @dragover.stop="dragover" :id="['videogrid_'+videosGroupValue+'_'+item.gridIndex+'_'+videoGridItem]" class="js_videogrid">
<div class="deleteVideo" title="删除" @click="delVideo('video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem)">x</div>
<video class="js-media" name="videoElement" :id="['video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem]" autoplay >
<p>你的浏览器不支持 HTML5 Video。</p>
</video>
</div>
4. 出现的第二个问题
拖拽视频调整顺序后,鼠标抬起,但弹窗依旧跟着动,像粘在鼠标上了一样。。。
5. 分析问题解决问题
鼠标左键抬起,拖拽的效果还在,而且是从子节点传递到父节点的事件,虽然我已经将拖拽开始事件阻止冒泡了(dragstart.stop),但是应该还是有什么事件漏出去给父节点了,那这个事件是什么呢? 只有鼠标按下去的事件了mousedown,所以将子节点的mousedown事件也阻止冒泡,修改后的代码:
<div v-for="videoGridItem in item.gridIndex" draggable="true" @mousedown.stop @dragstart.stop="videoDragstart" @dragend.stop="videoDragend" @drop.stop="videoDragenter" @dragover.stop="dragover" :id="['videogrid_'+videosGroupValue+'_'+item.gridIndex+'_'+videoGridItem]" class="js_videogrid">
<div class="deleteVideo" title="删除" @click="delVideo('video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem)">x</div>
<video class="js-media" name="videoElement" :id="['video_'+(index+1)+'_'+item.gridIndex+'_'+videoGridItem]" autoplay >
<p>你的浏览器不支持 HTML5 Video。</p>
</video>
</div>
6. 最终效果与总结
有些事件,是由多个事件组合而来的,比如click,就是由mousedown和mouseup组成的。涉及冒泡的时候要仔细考虑事件的顺序。