目标
推拽和放置是html5常用事件,利用Vue对事件的改造,实现一个从左边区域推拽元素,并放置到右边区域的功能
效果
概念
- 【源对象】拖拽的事件:
Html5 | Vue | 含义 | 备注 |
---|---|---|---|
ondragstart | 用户开始拖动元素时触发 | ||
ondrag | 元素正在拖动时触发 | ||
ondragend | 用户完成元素拖动后触发 |
- 【目标区域】放置的事件:
Html5 | Vue | 含义 | 备注 |
---|---|---|---|
ondragenter | 用户开始拖当被鼠标拖动的对象进入其容器范围内时触发此事件元素时触发 | ||
ondragover | 元素当某被拖动的对象在另一对象容器范围内拖动时触发此事件拖动时触发 | ||
ondragleave | 用户完成元素当被鼠标拖动的对象离开其容器范围内时触发此事件动后触发 | ||
ondrop | 在一个拖动过程中,释放鼠标键时触发此事件 |
必须给拖放区元素添加 dragover.prevent,才能使 drop 事件正确执行
源码
<template>
<div class="container">
<img id="img-text" src="@/assets/text.png" style="display: none;"/>
<img id="img-button" src="@/assets/button.png" style="display: none;"/>
<div class="left-warp">
<ul>
<li id="text" draggable="true" @dragstart="dragstart($event)">元素A</li>
<li id="button" draggable="true" @dragstart="dragstart($event)">元素B</li>
</ul>
</div>
<div :class="dragLines?'lines':''" id="item-room" class="right-warp" @dragenter="dragenter($event)" @dragleave="dragleave($event)" @drop="drop($event)" @dragover.prevent>
<ul>
<li v-for="(item,index) in arrs">{{item.text}}</li>
</ul>
</div>
</div>
</template>
<script type="text/javascript">
let elemetnNode=""//最先进入的地方
export default{
data(){
return{
arrs:[],
dragLines:false
}
},
methods:{
/**
* 拖动开始前
* e $event
*/
dragstart(e){
this.dragLines=true
e.dataTransfer.setData('id', e.target.id);
let imageText = document.getElementById('img-text').cloneNode();
let imageButton = document.getElementById('img-button').cloneNode();
if(e.target.id=='text'){
e.dataTransfer.setDragImage(imageText,150,150);
}
if(e.target.id=='button'){
e.dataTransfer.setDragImage(imageButton,150,150);
}
},
/**
* 放置目标
* @param {Object} e
*/
drop(e){
// console.log('drop::',e);
e.preventDefault()//阻止浏览器读取文件
let id = e.dataTransfer.getData('id');
if(id==='text'){
this.arrs.push({text:'元素A'})
}
if(id==='button'){
this.arrs.push({text:'元素B'})
}
this.dragLines=false
},
/**
* 进入目标区域时[待用]
* 默认区域内子目标都会出现进入,使用elemetnNode标记第一次进入的区域
* @param {Object} e
*/
dragenter(e){
elemetnNode=e.target;
console.log('drapenter')
},
/**
* 离开目标区域时[待用]
* 默认区域内子目标都会出现进入,使用elemetnNode标记第一次进入的区域
* @param {Object} e
*/
dragleave(e){
if(elemetnNode===e.target){
console.log('drapleave')
}
},
}
}
</script>
<style type="text/css" lang="scss" scoped>
.container{
height: 100%;
display: flex;
position: relative;
.left-warp{
height: 100%;
width: 200px;
background-color: #f9fcff;
padding: 20px;
ul li{
background-color: #e1edff;
margin-bottom: 10px;
height: 30px;
line-height: 30px;
text-align: center;
cursor: move;
}
}
.right-warp{
width: 100%;
background-color: #fff;
padding: 20px;
border: 1px dashed #fff;
ul li{
background-color: #e1edff;
margin-bottom: 10px;
height: 30px;
line-height: 30px;
text-align: center;
}
}
.lines{
border-color: #DD4A68;
}
}
</style>
解释
实现拖拽且放置,核心是三个事件:draggable="true"
,@dragstart
,@drop
draggable="true"
,@dragstart
– 源对象上使用,添加draggable="true"
,属性后,元素就可以被推拽了,默认是拖出一个半透明的源对象拷贝,但是不能放置- 在目标区域div使用
@drop
@dragstart
– 源对象上使用,使用dataTransfer
设置值,在放置时可以取出@drop
– 目标区域div上使用,使用dataTransfer
获取值,根据情况v-for
新元素e.dataTransfer.setData('id', e.target.id)
– 参考:dataTransfer对象e.dataTransfer.setDragImage(imageText,150,150)
– 设置推拽中跟随鼠标的图像,默认是源对象半透明图像,如果自定义跟随图像,必须是页面上存在的图片
Vue Drag and Drop
HTML5–拖放事件与dataTransfer对象