系统化学习前端之HTML(HTML5)

写在前面

前面已经梳理了HTML的基础标签使用,常规开发的话,基础标签已经完全满足日常工作了。但是,我们往往不满足于简单的页面,还需要提升,这个提升包括了页面SEO的提升、页面内容的提升以及页面交互的提升等等,语义化、canvas、音视频等特性也随之被催生出来。

语义化

语义化被提出,最重要的目的是提高页面的SEO。搜索引擎排名对目前的电商类网站有着举足轻重的地位,前端开发也开始规范化,定义标签不再清一色div和span嵌套了。

H5语义化标签

<header></header> 定义文档的页眉;

<footer></footer> 定义文档的页脚;

<nav></nav> 定义导航链接部分;

<section></section> 定义文档区块;

<article></article> 定义文档内容;

<aside></aside> 定义侧边栏部分;

<figure></figure> 定义独立区块,相对于原有div区块有缩进;

<figcaption></figcaption> 定义独立区块的标题,与figure配合使用;

<details></details> 定义关联内容描述,标题可折叠;

<summary></summary> 定义关联内容描述的标题,与detail配合使用;

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>HTML5</title>
</head>
<body>
	<div>
		<div>figure</div>
		<figure>
			<figcaption>title</figcaption>
			content: All the growth is a leap in the dark.
		</figure>
		<div>figure</div>
	</div>
	<div>
		<div>details</div>
		<details>
			<summary>标题</summary>
			content: All the growth is a leap in the dark.
		</details>
		<div>details</div>
	</div>
</body>
</html>

注意:部分语义化标签与原有标签的功能一致,只是标签名不同。

增强表单

输入列表

<datalist></datalist>本身不可见,为input标签提供输入建议,用户可从列表中选取输入,datalist与input通过id关联,具体用法如下:

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>HTML5</title>
</head>
<body>
	<datalist id="river">  
		<option>长江</option>  
		<option>嘉陵江</option>
		<option>金沙江</option>
		<option>黑龙江</option>
	</datalist>  
	<input type="text" list="river">
</body>
</html>

进度条

<progress value="10" max="100"></progress> 进度条控件,通过value属性指定进度,通过max定义最大范围;

刻度尺

<meter min="0" max="100" low="10" high="60" optimum="90" value="70"></meter> 用于标示一个值所处范围:判定value是否合适:value在min-low范围内为不可接受(红色),value在low-hight范围内为可以接受(黄色),value在high-max范围内为非常优秀(绿色);

输出

<output></output> 语义标签,无任何样式,相当于span,用法:<output>输出</output>

音视频

音频

音频标签使用如下:

<audio>
	<source src="xxx/xxx.mp3">  
	<source src="xxx/xxx.wav">  
	<source src="xxx/xxx.webm">  
	浏览器版本太低,无法播放音频。
</audio>

注意:audio标签默认生成300*32的inline-block,播放按照source源顺序执行,一旦成功播放,不执行后续,当所有音频无法播放,提示:浏览器版本太低,无法播放音频。

  1. audio标签属性:

    • autoplay
      自动播放,默认为false;

    • controls
      是否显示播放控件,默认为false;

    • loop
      循环播放,默认为false;

    • muted
      静音,默认为fasle;

    • preload
      音频的预加载策略;属性有:auto(预加载音频的元数据(部分画面)及缓冲一定时长视频,默认为auto),metadate(预加载音频的元数据),none(不预加载任何数据)

  2. audio-DOM对象

    可以通过dom操作获取audioDOM对象;

    • 属性

      • currentTime:当前播放时长;

      • duration:总时长;

      • paused:当前音频是否处于暂停状态;

      • volumn:当前音量,属性值为数字,范围(0-1);

      • playbackRate:播放速率,默认值为1,正常播放;

      • muted: 是否静音;

    • 方法

      • play() 播放;

      • pause() 暂停;

    • 事件

      • onplay:当前音频开始播放触发的事件;

      • onpause:当前音频暂停播放触发的事件;

视频

视频标签使用如下:

<video>
	<source src="xxx/xxx.mp4">  
	<source src="xxx/xxx.ogg">  
	<source src="xxx/xxx.webm">  
	浏览器版本太低,无法播放视频。
</video>

注意:video标签默认生成300*150的inline-block,播放按照source源顺序执行,一旦成功播放,不执行后续,当所有视频无法播放,提示:浏览器版本太低,无法播放视频。

  1. video标签属性:

    • autoplay
      自动播放,默认为false;

    • controls
      是否显示播放控件,默认为false;

    • loop
      循环播放,默认为false;

    • muted
      静音,默认为fasle;

    • preload
      音频的预加载策略;属性有:auto(预加载音频的元数据(部分画面)及缓冲一定时长视频,默认为auto),metadate(预加载音频的元数据),none(不预加载任何数据)

    • poster
      播放前显示海报 <video poster="xxx/xxx.png"></video>

  2. video-DOM对象

    可以通过dom操作获取videoDOM对象;

    • 属性

      • currentTime:当前播放时长;

      • duration:总时长;

      • paused:当前视频是否处于暂停状态;

      • volumn:当前音量,属性值为数字,范围(0-1);

      • playbackRate:播放速率,默认值为1,正常播放;

      • muted: 是否静音;

    • 方法

      • play() 播放;

      • pause() 暂停;

    • 事件

      • onplay:当前视频开始播放触发的事件;

      • onpause:当前视频暂停播放触发的事件;

Canvas

Canvas 是 HTML5 提出的绘图 API,绘制图形为位图。Canvas 的出现使得网页在不依赖图片(资源开销较大)的情况下,可以绘制各种图案。

Canvas 本质是一个 300 * 150 (默认大小) 的 inline-block,我们也称之为画布。绘制图像需要通过与画布绑定且唯一的画笔对象,使用相应的 api 进行绘制。

基本用法

  1. HTML 中创建画布
	<canvas width="400" height="400" id="c1"></canvas>
  1. JS 中获取画布,绑定画笔
	var c1 = document.getElementById("c1");
	var ctx = c1.getContext("2d"); // ctx 为画笔对象
  1. 通过 api 绘制图像
	ctx.strokeStyle = "red";
	ctx.strokeRect(10,10,100,100); // 坐标为(10, 10)的点处开始绘制宽高100的矩形
点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Canvas</title>
	<style type="text/css">
		#c1 {
			width: 400px;
			height: 400px;
			border: 1px solid #ccc;
		}
	</style>
</head>
<body>
	<!-- 分别注释 css 或者 canvas 宽高对比效果 -->
	<canvas width="400" height="400" id="c1">您的浏览器不支持 canvas 标签。</canvas>
	<script type="text/javascript">
		var c1 = document.getElementById("c1");
		var ctx = c1.getContext("2d");
		ctx.strokeStyle = "red";
		ctx.strokeRect(10,10,100,100)
	</script>
</body>
</html>

注意:

  1. 画布的宽高需要使用 html 属性或者 js 指定,不能使用 css 设置,因为 css 的宽高和 画布实际宽高是不一致的。
  2. Canvas 作图是有坐标轴概念的,例如A点至B点画一条实线,需要A,B点坐标。因此,画布的左上角定为坐标原点,左右为x轴(右为正),上下为y轴(下为正)。

绘图API

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Canvas</title>
	<style type="text/css">
		#c1 {
			border: 1px solid #ccc;
		}
	</style>
</head>
<body>
	<canvas width="400" height="400" id="c1"></canvas>
	<script type="text/javascript">
		var c1 = document.getElementById("c1");
		var ctx = c1.getContext("2d");

		// 可将绘制图形api 粘贴至此处观察效果。

	</script>
</body>
</html>
  1. 绘制基本线条

    • 绘制直线
    ctx.beginPath();
    ctx.moveTo(10,10); // 起始点(10,10)
    ctx.lineTo(100,10); // 终止点(100,10)
    ctx.stroke();
    
    • 绘制二次曲线
    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.quadraticCurveTo(200,100,300,300); // 终止点(300,300),控制点(200,100)
    ctx.stroke();
    
    • 绘制贝塞尔曲线
    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.bezierCurveTo(20,90,100,50,200,200); // 终止点(200,200),控制点1(20,90),控制点2(100,50)
    ctx.stroke();
    
    • 绘制圆弧
    ctx.beginPath();
    // 以(100,100)为圆心,半径为50,起点0弧度,终点1.5π弧度,顺时针画圆弧
    ctx.arc(100, 100, 50, 0, 2*Math.PI*0.75, false); 
    ctx.stroke();
    

    注意:arc()最后一个参数为Boolean类型,默认false表示顺时针,true表示逆时针,可缺省。

  2. 绘制简单形状

    • 绘制圆形
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2*Math.PI); // 以(100,100)为圆心,半径为50,顺时针画圆
    ctx.stroke();
    
    • 绘制矩形
    ctx.beginPath();
    ctx.rect(40,40,100,100)
    ctx.stroke();
    
    • 绘制三角形
    ctx.beginPath();
    ctx.moveTo(30,30);
    ctx.lineTo(150,150);
    ctx.lineTo(30,150);
    ctx.closePath(); // 闭合路径,使用直线连接起点和终点。
    ctx.stroke();
    
    • 绘制圆角矩形
    ctx.beginPath();
    ctx.moveTo(40,30);
    ctx.arcTo(130,30,130,130,10); // 控制点1(130,30),控制点2(130,130),半径为10
    ctx.arcTo(130,130,30,130,10);
    ctx.arcTo(30,130,30,30,10);
    ctx.arcTo(30,30,130,30,10);
    ctx.stroke();
    

    注意:arcTo()需要两个控制点绘制圆弧,具体使用可参照 MDN arcTo

  3. 绘制渐变

    • 绘制线性渐变
    var gradient = ctx.createLinearGradient(10,10,300,300); // 创建线性渐变对象,起点(10,10),终点(300,300)
    gradient.addColorStop(0, "blue");  // 设置比例及渐变色
    gradient.addColorStop(0.5, "red");  
    gradient.addColorStop(1, "#0f0");
    ctx.fillStyle = gradient; // 应用渐变色
    ctx.fillRect(10,10,300,300); // 绘制图形
    

    注意:canvas绘图有两种方式:fill() 填充 和 stroke() 描边,对应两种方式可以设置相应的属性 fillStyle 和 fillStyle。其他属性可参考 canvas 属性

    • 绘制径向渐变
    // 圆心为(160,160)生成半径30和100的圆,交集部分圆环为径向对象范围
    var gradient = ctx.createRadialGradient(160,160,30,160,160,100); 
    gradient.addColorStop(0, "blue");  
    gradient.addColorStop(0.5, "red");  
    gradient.addColorStop(1, "#0f0");
    ctx.fillStyle = gradient; 
    ctx.fillRect(10,10,300,300);
    
  4. 绘制特殊效果

    • 绘制阴影效果
    ctx.save(); // 保存当前画笔状态(无状态画笔)
    ctx.shadowBlur = 10; // 设置阴影模糊级数
    ctx.shadowOffsetX = 20; // 设置阴影水平偏移,可设置负值。
    ctx.shadowOffsetY = 20; // 设置阴影垂直偏移,可设置负值。
    ctx.shadowColor = 'black'; // 设置阴影颜色,不可使用 #fff
    ctx.fillStyle = '#00f';
    ctx.beginPath();
    ctx.fillRect(20,20,100,100);
    ctx.restore(); // 恢复上一次save的画笔状态(无状态画笔),save 和 restore 之间的画笔是阴影画笔,可注释这行,查看效果
    ctx.fillStyle = 'skyblue';
    ctx.beginPath();
    ctx.fillRect(150,20,100,100);
    
    • 绘制透明效果
    ctx.fillStyle = 'red';
    ctx.fillRect(20,20,100,100);
    ctx.globalAlpha = 0.2; // 设置透明度alpha为0.2,范围 0 - 1
    ctx.fillStyle = 'blue';
    ctx.fillRect(60,60,100,100);
    ctx.fillStyle = 'green'; // 未使用 save 和 restore, green 使用了 blue的 alpha为0.2的画笔
    ctx.fillRect(80,80,100,100);
    
  5. 绘制图像

    • 放缩图像
    var image = new Image(); //创建图片对象
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	ctx.drawImage(image, 10, 10, 200, 200) // 坐标(10,10)点处开始绘制图像,图像宽高 200*200,宽高可缺省,表示不放缩
    }
    

    注意:绘制图像一定要在图像加载完成以后,即onload触发以后。

    • 裁剪图像
    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	// 坐标(10,10)处,宽高 200*200 的图像,从坐标(20,20)处裁剪出宽高 50*50 的图像按照宽高 200*200显示。
    	ctx.drawImage(image, 20, 20, 50, 50, 10, 10, 200, 200) 
    }
    
    • 平铺图像
    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	var pattern = ctx.createPattern(image, 'repeat'); // createPattern设置平铺模式,可选值有:repeat(默认), repeat-x, repeat-y, no-repeat
    	ctx.fillStyle = pattern;
    	ctx.fillRect(5,5,395,395);
    }
    
    • 反转像素
    ctx.fillStyle = '#f00';
    ctx.fillRect(10,10,100,100);
    var imageData = ctx.getImageData(10,10,50,50); // 从坐标(10,10)处,获取图像信息对象,宽高为50*50
    for(var i=0;i<imageData.data.length;i+=4) { // imageData.data: ArrayBuffer包含了图像像素信息,以RGBA的顺序存放,范围0-255
    	imageData.data[i] = 255 - imageData.data[i];
    	imageData.data[i + 1] = 255 - imageData.data[i + 1];
    	imageData.data[i + 2] = 255 - imageData.data[i + 2];
    	imageData.data[i + 3] = 255;
    }
    ctx.putImageData(imageData,35,35); // 按照处理的图像信息(反转像素后的50*50图像),在坐标(35,35)处生成图像
    

    注意:反转像素使用的是填充矩形,使用 image 可以绘制图像,但获取像素信息会导致跨域报错:Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

    如下代码测试报错

    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	ctx.drawImage(image,10,10);
    	var imageData = ctx.getImageData(10,10,image.width,image.height)
    	console.log(imageData)
    }
    
  6. 绘制文本

    • 填充文本
    // font为综合属性,依次对应值:font-style  font-variant font-weight font-size/line-height font-family
    ctx.font="normal normal 400 30px/1.5 Microsoft YaHei"; 
    ctx.fillStyle = 'skyblue';
    ctx.fillText('Hello Canvas!', 50,50); // 坐标(50,50)处,绘制填充文本 Hello Canvas!
    
    • 描边文本
    ctx.font="normal normal 400 30px/1.5 Microsoft YaHei";
    ctx.strokeStyle = 'skyblue'; // 可以设置渐变,生成渐变文本
    ctx.strokeText('Hello Canvas!', 50,100);
    
  7. 绘制动画

    • canvas 动画相关API
    ctx.ratate(弧度); // 绘图旋转,轴为原点旋转,旋转具有累加效果;  
    ctx.translate(x,y);  // 绘图移动,原点由(0,0)移动到(x,y);  
    ctx.scale(x, y); // 绘图缩放,x,y表示缩放比例,>1表示放大,<1表示缩小;
    ctx.clearRect(0,0,c1.width,c1,height); // 从原点处,宽高为画布宽高,清除图像
    

    注意:clearRect() 是 canvas 绘制动画的关键 api,canvas 绘制动画的本质是一遍遍擦除重绘,如 canvas 时钟案例

Svg

Svg 是基于 XML 绘制的矢量图,Svg 图像是可以通过 DOM 元素获取的,并且可以通过 DOM 方法设置图像属性。

Svg 绘图类似于 Canvas 本质是一个 300*150 的 inline-block,也称之为画布。绘制图像是通过一系列 svg 标签,每个 svg 标签可以获取其 DOM 对象,并执行 DOM 操作。

基本用法

	<svg id="s1" width="400" height="400">
		<!-- svg 绘图标签 -->
	</svg>

绘图标签

  1. 绘制线条

    • 绘制直线
    <line x1="10" y1="10" x2="200" y2="200" style="stroke: blue; stroke-width: 3;" />
    

    注意:svg 与 canvas 一样具有坐标系概念,并且坐标系一致。

    • 绘制折线
    <polyline points="20,30 50,70 100,60 150,120" style="fill: none; stroke: #f00; stroke-width: 3;" />
    
    • 绘制曲线
    <path d="M 10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/>
    

    注意: path路径标签有很强大的功能,不单单是绘制曲线,根据d的value值命令不同,可以绘制更多图像。详细可以查看 path MDN

  1. 绘制简单形状

    • 绘制矩形
    <rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="2"/>
    
    • 绘制多边形
    <polygon points="50,160 55,180 70,180 60,190 65,205 50,195 35,205 40,190 30,180 45,180" stroke="green" fill="transparent" stroke-width="5"/>
    
    • 绘制圆
    <circle cx="25" cy="75" r="20" stroke="red" fill="transparent" stroke-width="5"/>
    
    • 绘制椭圆
    <ellipse cx="75" cy="75" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>
    
  2. 绘制渐变

    • 绘制线性渐变
    <defs>
    	<linearGradient id="linear" x1="0" x2="0" y1="0" y2="1">
    		<stop offset="0%" stop-color="red"/>
    		<stop offset="50%" stop-color="black" stop-opacity="0"/>
    		<stop offset="100%" stop-color="blue"/>
    	</linearGradient>
    </defs>
    <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#linear)"/>
    
    • 绘制径向渐变
    <defs>
    	<radialGradient id="radial" cx="0.25" cy="0.25" r="0.5">
    	<stop offset="0%" stop-color="red"/>
    	<stop offset="100%" stop-color="blue"/>
    	</radialGradient>
    </defs>
    <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#radial)"/>
    
  3. 绘制文本

    • 绘制填充文本
    <text x="30" y="80" fill="skyblue" style="font-size: 30px;">Hello Svg!</text>
    
    • 绘制描边文本
    <text x="30" y="40" fill="none" stroke="blue" stroke-width="1" style="font-size: 30px;">Hello Svg!</text>
    
  4. 绘制图像

    <image xlink:href="https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png" x="10" y="10" height="150px" width="200px"/>
    
  5. 绘制变换

    <rect x="20" y="20" width="20" height="20" transform="translate(30,40)" />
    <rect x="50" y="20" width="20" height="20" transform="rotate(45)" />
    <rect x="90" y="20" width="20" height="20" transform="scale(0.5, 1)" />
    

地理定位

HTML5 地理定位功能依托于浏览器 window.navigator.geolocation 属性,通过判断该属性是否存在可以检测浏览器是否支持地理定位功能。该属性包含三个地理定位 api:getCurrentPosition(), watchPosition(), clearPosition()

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>地理位置</title>
</head>
<body>
	<div>Geolocation</div>
	<script type="text/javascript">
		if(window.navigator.geolocation) {
			console.log(window.navigator.geolocation)
		} else {
			alert('您的浏览器不支持地理定位功能!')
		}
	</script>
</body>
</html>

getCurrentPosition

用于获取用户当前的地理位置信息,该方法有三个参数,success回调,error回调,options参数(可缺省)。

window.navigator.geolocation.getCurrentPosition(
	position => {
		console.log(position.timestamp, position.coords)
		// position.coords.latitude 纬度
		// position.coords.longtitude 经度
		// position.coords.altitude 海拔
		// position.coords.accuracy 经纬度的精度(米)
		// position.coords.altitudeAccuracy 海拔的进度(米)
		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
		// position.coords.speed 前进速度
	},
	error => {
		if(error.code === 1) {
			alert('用户拒绝位置服务')
		} else if(error.code === 2) {
			alert('获取不到位置信息')
		} else if(error.code === 3) {
			alert('获取位置信息超时')
		} else {
			console.log(error)
			alert('发生位置错误')
		}
	},
	{
		enableHighAccuracy: true, // 是否要求高精度的位置信息
		timeout: 100 * 1000,
		maximumAge: 30 * 1000, // 最大缓存时间
	}
)

watchPosition

用于持续监听用户当前的地理位置信息,地理位置发生变化自动调用该函数,参数与 getCurrentPosition 一致。

var watchId = window.navigator.geolocation.watchPosition(
	position => {
		console.log(position.timestamp, position.coords)
		// position.coords.latitude 纬度
		// position.coords.longtitude 经度
		// position.coords.altitude 海拔
		// position.coords.accuracy 经纬度的精度(米)
		// position.coords.altitudeAccuracy 海拔的进度(米)
		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
		// position.coords.speed 前进速度
	},
	error => {
		if(error.code === 1) {
			alert('用户拒绝位置服务')
		} else if(error.code === 2) {
			alert('获取不到位置信息')
		} else if(error.code === 3) {
			alert('获取位置信息超时')
		} else {
			console.log(error)
			alert('发生位置错误')
		}
	},
	{
		enableHighAccuracy: true,
		timeout: 3 * 1000,
		maximumAge: 30 * 1000,
	}
)

注意:watchPosition 会返回一个句柄,本质是一个数字,类似 setInterval 返回一致,该句柄用于停止监听。

clearPosition

用于停止 watchPosition 的监听,该方法有一个参数:watchPosition() 的返回值。

var watchId = window.navigator.geolocation.watchPosition(
	position => {
		console.log(position.timestamp, position.coords)
		// position.coords.latitude 纬度
		// position.coords.longtitude 经度
		// position.coords.altitude 海拔
		// position.coords.accuracy 经纬度的精度(米)
		// position.coords.altitudeAccuracy 海拔的进度(米)
		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
		// position.coords.speed 前进速度
	},
	error => {
		if(error.code === 1) {
			alert('用户拒绝位置服务')
		} else if(error.code === 2) {
			alert('获取不到位置信息')
		} else if(error.code === 3) {
			alert('获取位置信息超时')
		} else {
			console.log(error)
			alert('发生位置错误')
		}
	},
	{
		enableHighAccuracy: true,
		timeout: 3 * 1000,
		maximumAge: 30 * 1000,
	}
)

window.navigator.geolocation.clearPosition(watchId)

注意:以上方法可以获取用户的地理位置信息,但是我们获取都是经纬度和海拔信息,无法转换成常规的地址信息。因此,需要借助地图 API 做逆地址解析,如 百度地图 BMap高德地图 AMap

Web Worker

Web Worker是多线程工作,运行在后台的JavaScript,无法请求或访问页面,不会影响页面性能。

基本用法

  1. 主进程中创建 worker 对象

    var worker = new Worker('./worker.js')
    
  2. 数据传递

    • 主线程传递数据
    worker.postMessage(params); // postMessage只接受一个参数
    
    • worker 线程传递数据
    self.postMessage(params); // self 可省略,即 postMessage();
    
  3. 接收数据

    • 主线程接收数据
    worker.onmessage = function(event) {
    	event.data // worker 传递的参数
    }
    
    • worker 线程接收数据
    self.onmessage = function(event) {
    	event.data // 主线程传递的参数
    }
    
  4. 关闭 worker 线程

    • 主线程关闭 worker 线程
    worder.terminate();
    
    • worker 线程内部关闭
    self.close();
    

    注意:web worker 需要加载 worker.js 文件,而浏览器因同源策略无法加载本地文件,需要借助服务器将 worker.js 资源静态化,可参照 web worker demo

Web Storage

sessioStorage

sessioStorage 将数据保存在 session 对象中,而 session 对象是浏览器打开窗口的过程中,为用户浏览网站提供的内存对象(session 对象与窗口绑定),一旦浏览器关闭,内存会被清空。因此,sessioStorage 是临时存放数据,随浏览器关闭而销毁。

sessioStorage.setItem(key,value); // key, value 必须为字符串
sessioStorage.getItem(key);
sessioStorage.removeItem(key;
  1. 清空
sessioStorage.clear();

注意:浏览器同源策略对 sessioStorage 的影响:

  1. 不同源的情况下,A,B 页面是断然无法共享 sessioStorage 的。

  2. 同源的情况下,B 页面由 A 页面中链接导航打开,则 B 页面 session 对象是 A 页面 session 对象的复制,且为值引用,相互对立,不受干扰。

  3. 同源的情况下,A,B 页面是不同窗口分别打开的,则 A,B 页面的 session 对象无关联。

localStorage

localStorage 将数据保存在客户端本地,通常保存在磁盘或其他存储介质中,浏览器关闭不会影响磁盘和存储介质(存储与”源“绑定)。因此,localStorage 是永久存储(不主动清理和损毁磁盘的情况下)。

localStorage.setItem(key,value); // key, value 必须为字符串,引用类型数据可以通过JSON方式进行存储,JSON API: JSON.stringify(), JSON.parse()
localStorage.getItem(key);
localStorage.removeItem(key;
  1. 清空
localStorage.clear();

注意:浏览器同源策略对 localStorage 的影响:

  1. 不同源的情况下,A,B 页面是断然无法共享 localStorage 的。

  2. 同源的情况下,A,B 页面共享 localStorage,共用同一存储,相互干扰,相互影响,可以监听 storage 事件来观测 local 数据变化。

Web SQL

Web SQl 是客户端数据库,同服务器端 SQL Serve 和 Oracle 一致,可以使用 SQL 语句进行一些数据库操作,如表和数据的增删改查等;Web SQL的三个核心 API:

openDatabase

用于打开或创建数据库对象的方法,指定数据名,存在即打开,不存在则创建;

var db = openDatabase('testDB', '1.0', 'this is a db for test', 5 * 1024 * 1024) // 参数分别为:数据库名称,版本,描述,大小
if(!db) {
	alert('创建/打开 数据库失败')
} else {
	// 执行数据库操作(transacion, executeSql)
	alert('创建/打开 数据库成功')
}

transacion

用于创建并控制事务,可进行事务提交和回滚。事务:一系列数据操作的集合,所有操作完成,事务提交,否则,事务回滚,取消所有操作。

  1. 创建表操作
const createTabelSQL = "create table if not exists User (id UNIQUE, name TEXT)"
const createData = []

db.transaction(res => {
	res.executeSql(
		createTabelSQL,
		createData,
		success => {
			alert('创建 User 表成功')
		},
		error => {
			alert('创建 User 表失败,原因:', error.message)
		}
	)
})
  1. 删除表操作
const dropSQL = "drop table User"
const dropData = []

db.transaction(res => {
	res.executeSql(
		dropSQL,
		dropData,
		success => {
			alert('表 User 删除成功')
		},
		error => {
			alert('表 User 删除失败,原因:', error.message)
		}
	)
})

注意:transacion 参数为回调函数,回调函数内部执行 executeSql。

executeSql

用于执行 SQL 操作,参数有四个,分别为:sql,data,success回调, error回调。

  1. 插入数据
const insertSQL = "insert into User(id, name) values(?, ?)"
const insertData = [1, '张三']

db.transaction(res => {
   res.executeSql(
   	insertSQL,
   	insertData,
   	success => {
   		alert('数据插入成功')
   	},
   	error => {
   		alert('数据插入失败,原因:', error.message)
   	}
   )
})
  1. 更新数据
const updateSQL = "update User set name=? where id=?"
const updateData = ["李四", 1]

db.transaction(res => {
   res.executeSql(
   	updateSQL,
   	updateData,
   	success => {
   		alert('更新 User 表成功')
   	},
   	error => {
   		alert('更新 User 表失败,原因:', error.message)
   	}
   )
})
  1. 查询数据
const selectSQL = "select * from User"
const selectData = []

db.transaction(res => {
   res.executeSql(
   	selectSQL,
   	selectData,
   	(success, data) => {
   		console.log(data.rows)
   	},
   	error => {
   		alert('数据查询失败,原因:', error.message)
   	}
   )
})
  1. 删除数据
const deleteSQL = "delete from User"
const deleteData = []

db.transaction(res => {
  res.executeSql(
  	deleteSQL,
  	deleteData,
  	success => {
  		alert('数据删除成功')
  	},
  	error => {
  		alert('数据删除失败,原因:', error.message)
  	}
  )
})

注意:executeSql 第二个参数是必须的,为空可以设置为空数组。此外,SQL 语句中可以使用 ? 占位符,按照顺序对应 data 中的数据项。

Web Socket

Web Socket 是全双工通信,应用 Web Socket 技术可以做到:web 端在任意时刻请求服务端,服务端在任意时刻推送 web 端;与 http 相比,Web Socket 解决了服务端无法主动向 web 端推送的功能,更是有效解决了消息时效性问题,目前多应用于响应系统。

基于 nodejs 的使用

  1. web 端:
let ws = new WebSocket('ws://127.0.0.1:3000/public')
ws.onopen = () => {
	ws.send('hello server')
};
ws.onmessage = ev => {
	console.log(ev.data)
}
  1. 服务端:
const express = require('express')
const path = require('path')
const http = require('http')
const Ws = require('ws').Server

const app = express()
app.use('/public',express.static(path.resolve(__dirname, './public/')))

const server = http.createServer(app)
server.listen(3000)

let wsServer = new Ws({ server })
wsServer.on('connection', socket => {
  socket.on('message', msg => {
    console.log('客户端发送过来的消息:' + msg);
    socket.send('服务器说:你好客户端')
  })
});

注意:上例是使用 ws 模块进行的简单使用,项目地址:web socket demo,市场上有多种 web socket库,调用方式也不同,如 socket.io 库

拖放 API

拖放 API 是指:drag 和 drop 行为过程触发的 7 个事件,以及拖放的两个对象:源对象(拖的对象),目标对象(放的对象)。

在 HTML5 当中,任何元素均可以被拖放,但是实施拖放必须指定元素属性 draggable = true

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>拖放 API</title>
	<style type="text/css">
		#origin {
			width: 100px;
			height: 100px;
			background-color: skyblue;
			float: left;
		}
		#desination {
			width: 200px;
			height: 200px;
			background-color: orchid;
			float: right;
			margin-right: 100px;
		}
	</style>
</head>
<body>
	<div id="origin" draggable="true"></div>
	<div id="desination"></div>
	<script type="text/javascript">
		const origin = document.getElementById('origin')

		origin.addEventListener('dragstart',function(event) {
			console.log('拖 开始')
			console.log(event)
		})

		origin.addEventListener('drag', function(event) {
			console.log('拖 进行')
		})

		origin.addEventListener('dragend', function(event) {
			console.log('拖 结束')
		})


		const desination = document.getElementById('desination')

		desination.ondragenter = function(event) {
			console.log('拖 进入')
		}

		desination.ondragover = function(event) {
			console.log('拖 悬停')
			// event.preventDefault()
		}

		desination.ondragleave = function(event) {
			console.log('拖 离开')
		}

		desination.ondrop = function(event) {
			console.log('放')
		}

	</script>
</body>
</html>

源对象和目标对象

发生拖放行为,则存在两个相对物体,即 A 物体 放置 B 物体上,我们称之 A 物体为源对象,B 物体为目标对象。

  1. 源对象(origin)
  • origin.ondragstart
    拖动开始触发的事件,拖放过程执行 1 次。

  • origin.ondrag
    拖动过程中触发的事件,拖放过程执行 多 次。

  • origin.ondragend
    拖动结束触发的事件,拖放过程执行 1 次。

  1. 目标对象
  • desination.ondragenter
    源对象进入目标对象区域触发的事件,拖放过程执行 1 次。

  • desination.ondragover
    源对象悬停目标对象上方触发的事件,拖放过程执行 n 次。

  • desination.ondragleave
    源对象离开目标对象区域触发的事件,拖放过程执行 0 或 1 次。

  • desination.ondrop
    源对象在目标对象上方释放时触发的事件,拖放过程执行 0 或 1 次。

注意:dragover 默认行为是悬停上方,释放后立即执行 dragleave,而释放后执行 drop 需要阻止 dragover 默认行为,因此执行 dragleave 或 drop 是需要根据 dragover 是否阻止默认行为来决定的。

dataTransfer

拖放事件对象中存在一个 dataTransfer 对象,可以通过这个对象进行拖放过程中的交互。

源对象和目标对象可以借助 dataTransfer 对象的 setData() 和 gerData() 方法进行数据传递;

const origin = document.getElementById('origin')

origin.addEventListener('dragstart',function(event) {
	console.log('拖 开始')
	event.dataTransfer.setData('name', 'blue block')
})

const desination = document.getElementById('desination')

desination.ondragover = function(event) {
	event.preventDefault()
}

desination.ondrop = function(event) {
	console.log('放')
	const name = event.dataTransfer.getData('name')
	console.log(name)
}

注意:dataTransfer 对象的 setDragImage() 方法可以自定义拖放图标,该方法有三个参数:image,图标与 x 轴偏移量,图标与 y 轴偏移量。

后记

HTML5 新特性暂时更新致此吧,还有其他特性会以碎片化学习前端系列更新。博客中新特性均是基本使用,没有涉及工作中的应用场景,我的考虑是先广而全,后精而深,慢慢会结合场景更新。

posted @ 2023-02-20 16:28  深巷酒  阅读(11)  评论(0编辑  收藏  举报