重学前端 浏览器支持(添加新元素)/ 拖放(第八天)

该文章于2020/8/21改,主要针对 重学前端第一阶段完 钢琴项目(document.querySelector js改变css样式的3种方式 思路 成品) 的拖动的解析!

文章目录

  • HTML5 浏览器支持
  • HTML5 拖放
    • 一、设置元素为可拖放(draggable)
    • 二、dataTransfer.setData()
      • target
      • DataTransfer 对象
    • 三、拖动事件
    • 四、放到何处ondragover
      • event.preventDefault()
    • 五、进行放置ondrop

HTML5 浏览器支持

一、将 HTML5 元素定义为块元素

HTML5 定了 8 个新的 HTML 语义(semantic) 元素。所有这些元素都是 块级 元素。

为了能让旧版本的浏览器正确显示这些元素,你可以设置 CSS 的 display 属性值为 block:

实例:

header, section, footer, aside, nav, main, article, figure {
    display: block; 
}

二、为 HTML 添加新元素

你可以为 HTML 添加新的元素

该实例向 HTML 添加的新的元素,并为该元素定义样式,元素名为 < myHero> :

实例:

DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8"> 
		<title>为 HTML 添加新元素title>
		<script> //为IE添加新的元素,其它浏览器可不用。Internet Explorer 8 及更早 IE 版本的浏览器不支持该方式。
			document.createElement("myHero")
		script>
		<style>
			myHero {
			    display: block;
			    background-color: #ddd;
			    padding: 50px;
			    font-size: 30px;
			}
		style> 
	head>
 
	<body>
		<h1>我的第一个标题h1>
		<p>我的第一个段落。p>
		<myHero>我的第一个新元素myHero>
	body>
html>

HTML5 拖放

拖放是一种常见的特性,即抓取对象以后拖到另一个位置,在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放

实例:

DOCTYPE HTML>
<html>
<head>
	<meta charset="utf-8"> 
	<title>菜鸟教程(runoob.com)title>
	<style type="text/css">
		#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
	style>
	<script>
		function allowDrop(ev)
		{
			ev.preventDefault();
		}
		
		function drag(ev)
		{
			ev.dataTransfer.setData("Text",ev.target.id);
		}
		
		function drop(ev)
		{
			ev.preventDefault();
			var data=ev.dataTransfer.getData("Text");	
			ev.target.appendChild(document.getElementById(data));
		}
	script>
head>

	<body>
		<p>拖动 RUNOOB.COM 图片到矩形框中:p>
		<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">div>
		<br>
		<img id="drag1" src="/images/logo.png" ondragstart="drag(event)" width="336" height="69">
	body>
html>

接下来就将整个拖放,分成一小块一小块的来讲解:

一、设置元素为可拖放(draggable)

首先,为了使元素可拖动,把 draggable 属性设置为 true

<img draggable="true">  //draggable可省略

draggable 属性规定元素是否可拖动。

提示

  • 链接 和 图像 默认是可拖动的
  • draggable 属性经常用于拖放操作

重学前端 浏览器支持(添加新元素)/ 拖放(第八天)_第1张图片
draggable属性浏览器支持:
在这里插入图片描述

二、dataTransfer.setData()

规定当元素被拖动时,会发生什么?

dataTransfer.setData() 方法设置被拖数据的数据类型和值

function drag(ev)
{
    ev.dataTransfer.setData("Text",ev.target.id);
}

Text 是一个 DOMString 表示要添加到 drag object 的拖动数据的类型是可拖动元素的 id (“drag1”)。

DataTransfer.setData() 方法用来设置拖放操作的 内容 到指定的数据和类型

如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得 类型列表(types 列表) 中的最后一个项目将是新类型。

如果给定类型的数据已经存在,现有数据将被替换为相同的位置,也就是说,替换相同类型的数据时 类型列表(types 列表) 的顺序不会更改。
重学前端 浏览器支持(添加新元素)/ 拖放(第八天)_第2张图片
format
一个 DOMString 表示要添加到 drag object的拖动数据的类型

data
一个 DOMString表示要添加到 drag object的数据

target

target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。

DataTransfer 对象

在处理拖放操作时,我们需要用到 DataTransfer 对象来保存被拖动的数据, DataTransfer 可以保存一项或多项数据、一种或者多种数据类型。

属性:
重学前端 浏览器支持(添加新元素)/ 拖放(第八天)_第3张图片
方法:
重学前端 浏览器支持(添加新元素)/ 拖放(第八天)_第4张图片
(好多天来,总算学习了,不想放手,可是得去洗了,呜呜呜,明明可以写得更好,算了,明天再来!!!(ㄒoㄒ)~~)

三、拖动事件

ondragstart 事件在用户开始拖动元素或选择的文本时触发。在上面的例子中,ondragstart 属性调用了一个函数drag(event),它规定了被拖动的数据

在拖放的过程中会触发以下事件:

一、在拖动目标上触发事件 (源元素):

  • ondragstart : 用户开始拖动元素时触发
  • ondrag : 元素正在拖动时触发
  • ondragend : 用户完成元素拖动后触发

二、释放目标时触发的事件:

  • ondragenter : 当被鼠标拖动的对象进入其容器范围内时触发此事件
  • ondragover : 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
  • ondragleave : 当被鼠标拖动的对象离开其容器范围内时触发此事件
  • ondrop : 在一个拖动过程中,释放鼠标键时触发此事件

重学前端 浏览器支持(添加新元素)/ 拖放(第八天)_第5张图片
注意:

当一个对象处于拖动时,其绑定在window上,而非父元素上,通过console.log(this); 可以看出


实例:

function ondragstart(event){
	console.log(this);
	event.dataTransfer.setData("Text", event.target.id);
}

打印出来的结果就是widow!

四、放到何处ondragover

ondragover 事件规定在何处放置被拖动的数据,默认地,无法将 数据/元素 放置到其他元素中,如果需要设置允许放置,我们必须阻止对元素的默认处理方式

这要通过调用 event.preventDefault() 方法。

event.preventDefault()

如果事件可以被取消,就取消事件(即取消事件的预设行为),但不会影响事件的传递,事件仍会继续传递。

这里Firefox会产生依旧打开新标签,但没有东西的bug,需要加上ev.stopPropagation(); (在我的 成品 里可以看见)

五、进行放置ondrop

当放置被拖数据时,会发生 ondrop 事件。

在上面的例子中,ondrop 属性调用了一个函数,drop(event):

function drop(ev)
{
    ev.preventDefault();
    var data=ev.dataTransfer.getData("Text");
    ev.target.appendChild(document.getElementById(data));
}

代码解释:

调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)


通过 dataTransfer.getData(“Text”) 方法获得被拖的数据,该方法将返回在 setData() 方法中设置为相同类型的任何数据。


被拖数据是被拖元素的 id (“drag1”)


把被拖元素追加到放置元素(目标元素)中

注意
在追加元素的的时候,经常会报错:Uncaught TypeError: Failed to execute ‘appendChild’ on ‘Node’: parameter 1 is not of type ‘Node’

这其实是一个很好解决的问题,其实就是 appendChild()需要传入的是一个dom的对象,而不是dom的字符串,这里菜鸟试了一下,通过 document.xxxxx 得到的都是对象!(如果有误,望读者指出)

注意
这里使用 ev.target 会产生看不懂的情况,就是拖动多个进同一个容器,结果不会出现上面如下的情况:

如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得 类型列表(types 列表) 中的最后一个项目将是新类型。

如果给定类型的数据已经存在,现有数据将被替换为相同的位置,也就是说,替换相同类型的数据时 类型列表(types 列表) 的顺序不会更改。

这是为什么呢?

因为 ev.target 会把先移入的img,当作目标节点,所以把再次移入的内容加入到img里面,而不是其父元素中;当然如果父元素比较大,你没有移动到先移入的元素上,也不会产生bug。

这里最好的解决办法就是将ondrop事件绑定到元素上,eg:οndrοp=“drop(event,this)” ,然后js就可以直接

function drop(ev,element) {
    ev.preventDefault();
    ev.stopPropagation();
    // 阻止浏览器对拖动的默认处理,但是firefox有点小bug
    // 加上ev.stopPropagation();已解决firefox的bug
    var data = ev.dataTransfer.getData("Text");
	element.appendChild(document.getElementById(data));
}

你可能感兴趣的:(重学前端1,HTML,详解html拖拽,html拖放,阻止默认事件)