小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
学习拖拽,主要是学习拖拽事件,根据应用于被拖拽元素和应用于目标元素的不同,我们一般可以将拖拽事件分类:
- 应用于被拖拽元素的拖拽事件:
- ondragstrat:当拖拽开始时调用;
- ondrag:当拖拽的时候,在整个拖拽过程都会调用
- ondragleave:当鼠标离开拖拽元素的时候调用
- ondragend:当拖拽结束时调用
触发顺序: 1-->ondragstart 拖拽开始 2-->ondrag 拖拽过程中(持续拖拽 持续触发) 3-->ondragleave 离开拖拽元素时 4--> ondrag 还在拖拽过程中(持续拖拽 持续触发) 5--> 拖拽结束
- 拖拽事件应用于目标元素:
- ondragenter:应用于目标元素,当拖拽元素进入目标元素时调用;
- ondragover:当拖拽元素停留在目标元素上时调用;
- ondrop:当拖拽元素在目标元素上松开鼠标放下时调用; 注意:浏览器有个默认行为,默认阻止ondrop事件:那么我们必须在ondragover中阻止浏览器的默认行为。
- ondragleave:当鼠标离开目标元素时调用
使用上面的这些事件,写个简单的拖拽案例:
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<style type="text/css">
p{
background-color: #888;
}
div{
width: 200px;
height: 200px;
border: 1px solid red;
float: left;
margin-left: 50px;
}
</style>
</head>
<body>
<div class="div1" id="div1">
<p id="pe" draggable="true">试着把我拖过去</p>
</div>
<div class="div2" id="div2"></div>
<script type="text/javascript">
//被拖拽元素
var p = document.querySelector("#pe");
p.ondragstart = function(){
console.log('ondragstart 拖拽开始了');
}
p.ondragend = function(){
console.log('ondragend 拖拽结束了');
}
p.ondragleave = function(){
console.log('ondragleave 离开拖拽元素了');
}
p.ondrag = function(){
console.log('ondrag 拖拽过程中');
}
// 拖拽目标
var div2 = document.querySelector("#div2");
div2.ondragenter=function(){
console.log("ondragenter 拖拽元素进入目标元素了");
}
div2.ondragover = function(e){
// 注意:浏览器有个默认行为,默认阻止ondrop事件:那么我们必须在ondragover中(一定要这里)阻止浏览器的默认行为。
console.log("ondragover 拖拽元素在目标元素上时");
e.preventDefault();
}
div2.ondrop = function(){
// 注意:浏览器有个默认行为,默认阻止ondrop事件:那么我们必须在ondragover中阻止浏览器的默认行为。
console.log("ondrop 拖拽元素在目标元素上松开鼠标放下");
// 添加被拖拽的元素到当前目标元素。
div2.appendChild(p);
}
div2.ondragleave = function(){
console.log("ondragleave:鼠标离开目标元素了");
}
// 拖拽回去
var div1 = document.querySelector("#div1");
div1.ondragover = function(e){
e.preventDefault();
}
div1.ondrop = function(){
div1.appendChild(p);
}
</script>
</body>
</html>
当上面的例子还是有很大的问题,只能指定元素拖拽到指定位置,太局限。 很多时候,我们希望多个元素能被拖拽,同时也有多个目标元素,即:我希望能够任意个被拖拽元素,拖拽到任意一个目标元素中: 核心是:通过事件捕获来获取当前被拖拽的元素;先存储起来,再通过事件捕获找到目标元素,然后再目标元素中使用开始被存储的值来添加元素。
<body>
<div class="div1" id="div1">
<p id="pe" draggable="true">试着把我拖过去</p>
</div>
<div class="div2" id="div2"></div>
<script type="text/javascript">
var obj = null;//定义当前被拖拽的元素
//被拖拽元素
document.ondragstart = function(e){
// 通过事件捕获来获取当前被拖拽的元素;
// e.target事件源对象
e.target.style.opacity = '.5';
e.target.parentNode.style.borderWidth = "3px";
//将被拖拽的元素放到一个全局对象中保存,当拖拽的结束的时候添加到目标元素中。
obj = e.target;
}
document.ondragend = function(e){
e.target.style.opacity = '1';
e.target.parentNode.style.borderWidth = "1px";
}
// 拖拽目标
document.ondragover = function(e){
e.preventDefault();
}
document.ondrop = function(e){
e.target.appendChild(obj);
}
</script>
</body>
当时这种情况有个问题:使用了一个全局变量obj;一般情况下我们不到最后的时候都不要使用全局变量,以为使用全局变量有两个问题: 1.不安全,全局变量任何人都能使用,你也可以该,我也可以该; 2.全局变量会导致内存泄漏;
为了解决上述问题 ,我们使用另外一种方式来存储这个全局对象; 通过dataTransfer来实现数据的存储和获取:
通过事件对象e中的dataTransfer里的setData()来实现数据的存储和获取 setData(format,data); format:数据类型,一般有两种:text/html、text/uri-list data:数据:一般来说是字符串 这里设置的值,只能在ondrop里面取得;
存储
e.dataTransfer.setData("text/html",e.target.id)
获取:
var id = e.dataTransfer.getData("text/html");
e.target.appendChild(document.getElementById(id));
完整代码:
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<style type="text/css">
p{
background-color: #888;
}
div{
width: 200px;
height: 200px;
border: 1px solid red;
float: left;
margin-left: 50px;
}
</style>
</head>
<body>
<div class="div1" id="div1">
<p id="pe" draggable="true">试着把我拖过去</p>
</div>
<div class="div2" id="div2"></div>
<script type="text/javascript">
//被拖拽元素
document.ondragstart = function(e){
e.target.style.opacity = '.5';
e.target.parentNode.style.borderWidth = "3px";
obj = e.target;
// 通过事件对象e中的dataTransfer里的setData()来实现数据的存储和获取
// setData(format,data);
// format:数据类型,一般有两种:text/html、text/uri-list
// data:数据:一般来说是字符串
//这里设置的值,只能再ondrop里面取得;
e.dataTransfer.setData("text/html",e.target.id);
}
document.ondragend = function(e){
e.target.style.opacity = '1';
e.target.parentNode.style.borderWidth = "1px";
}
// 拖拽目标
document.ondragover = function(e){
e.preventDefault();
}
document.ondrop = function(e){
// 通过dataTransfer.setData()存储的数据只能再ondrop事件中获取;
var id = e.dataTransfer.getData("text/html");
e.target.appendChild(document.getElementById(id));
}
</script>
</body>
</html>