【H5系列-7】关于拖拽你了解吗

334 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

学习拖拽,主要是学习拖拽事件,根据应用于被拖拽元素和应用于目标元素的不同,我们一般可以将拖拽事件分类:

  1. 应用于被拖拽元素的拖拽事件:
  • ondragstrat:当拖拽开始时调用;
  • ondrag:当拖拽的时候,在整个拖拽过程都会调用
  • ondragleave:当鼠标离开拖拽元素的时候调用
  • ondragend:当拖拽结束时调用

触发顺序: 1-->ondragstart 拖拽开始 2-->ondrag 拖拽过程中(持续拖拽 持续触发) 3-->ondragleave 离开拖拽元素时 4--> ondrag 还在拖拽过程中(持续拖拽 持续触发) 5--> 拖拽结束

  1. 拖拽事件应用于目标元素:
  • 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>