前言
在了解HTML5之前,我们先来了解一下什么是HTML和HTML5
HTML的全称为超文本标记语言(Hyper Text Markup Language),是一种标记语言。它包括一系列标签,HTML标签可以说明文字,图形、动画、声音、表格、链接等,通过这些标签编写成一个让浏览器能识别的.html文件。它的版本发展历程为HTML 1.0 > HTML 2.0 > HTML 3.2 > HTML 4.0 > HTML 4.01
HTML5是由W3C(万维网联盟)在2007年成立的,旨在满足互联网应用迅速发展的需求,提供一个统一的、开放的网页标准,代表了网页标记语言的新标准,也标志着网页应用开发进入了一个新的时代,拥有比HTML更丰富的特性的同时,也废弃了一些标签特性。
##HTML5的特性有那些?
- 新增加了一些语义标签
- 增强型表单
- 视频和音频
- Canvas绘图
- SVG绘图
- 地理定位
- 拖拽API
- WebWorker
- WebStorage
- WebSocket
- 移除部分标签
语义标签
这些新的语义元素有助于更准确地描述文档的结构,提高文档的可读性和可访问性。使用这些元素有助于浏览器、搜索引擎和辅助技术更好地理解和解释页面内容,更有利于SEO优化,方便爬虫爬取网页,增加曝光度。
| 标签 | 描述 |
|---|---|
| article | 定义页面独立的内容区域 |
| aside | 定义页面的侧边栏内容 |
| bdi | 允许您设置一段文本,使其脱离其父元素的文本方向设置 |
| details | 用于描述文档或文档某个部分的细节 |
| dialog | 定义对话框,比如提示框 |
| summary | 标签包含details元素的标题 |
| figure | 规定独立的流内容(图像、图表、照片、代码等等) |
| figcaption | 定义figure元素的标题 |
| header | 定义了文档的头部区域 |
| footer | 定义section或document的页脚 |
| mark | 定义带有记号的文本(实际是高亮文本内容) |
| meter | 定义度量衡。仅用于已知最大和最小值的度量 |
| nav | 定义导航链接的部分 |
| progress | 定义任何类型的任务的进度 |
| ruby | 定义ruby注释(中文注音或字符) |
| rt | 定义字符(中文注音或字符)的解释或发音 |
| rp | 在ruby注释中使用,定义不支持ruby元素的浏览器所显示的内容 |
| section | 定义文档中的节(section、区段) |
| time | 定义日期或时间 |
| wbr | 规定在文本中的何处适合添加换行符 |
<!--用于表示页面中独立的、完整的、可以独立分配的内容。通常用于文章、博客帖子等-->
<article>
<h2>文章标题</h2>
<p>文章内容...</p>
</article>
<!--用于表示与页面内容相关的辅助信息。通常包含侧边栏、广告、引用等-->
<aside>
<h2>这里是侧边栏</h2>
<p>相关链接...</p>
</aside>
<!--用于设置大一号文字(最大7号),并且可以设置文字方向(感觉这个没啥用)-->
<p>外面小一号文字<big dir="rtl">这是大一号的文本111。</big></p>
<!--用于展示详情内容,和tree树结构类似-->
<details>
<summary>显示的标题</summary>
<p> 折叠隐藏的内容1</p>
<p>折叠隐藏的内容2</p>
</details>
<!--在页面中间展示一个窗口结构-->
<dialog open> 窗口内容</dialog>
<!--在页面中规定独立的流内容(图像、图表、照片、代码等等)展示区域-->
<figure>
<img src="xxx.img" >
<figcaption>这是一张图片</figcaption>
</figure>
<!--header规定页面的头部,footer规定页面的底部-->
<header>头部</header>
<footer>底部</footer>
<!--mark内容会高亮-->
今天要<mark>吃鸡腿</mark>
<!--类似一个进度条,展示设置的百分比值或者指定的max和value-->
<meter value="2" min="0" max="10"></meter>
<meter value="0.6"></meter>
用于包含导航链接的部分,通常包含页面的主导航
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/">关于我们</a></li>
<li><a href="/">联系我们</a></li>
</ul>
</nav>
<!--进度条,一般可以设置下载进度-->
<progress value="22" max="100"></progress>
<!--很方便的功能,标注,下面有运行效果-->
<ruby>
汉 <rp>(</rp><rt>Han</rt><rp>)</rp>
字 <rp>(</rp><rt>Zi</rt><rp>)</rp>
</ruby>
<!--如下是运行结果-->
Han Zi
汉 字
<!--定义了一个区域-->
<section>这是一个区域</section>
<!--time标签不会在任何浏览器中呈现任何特殊效果,只是用来给机器识别的-->
<!--该元素能够以机器可读的方式对日期和时间进行编码,这样,举例说,用户代理能够把生日提醒或排定的事件添加到用户日程表中,搜索引擎也能够生成更智能的搜索结果-->
<p>我今年的生日要<time datetime="2024-06-01">吃蛋糕</time></p>
<!-与<br>标签不同,如果浏览器窗口的宽度足够,则不换行;反之,则在添加了 <wbr> 标签的位置进行换行-->
我要吃<wbr>麦当当</wbr>
ps:各个浏览器对语义标签的支持情况不一样,使用的时候建议去查阅一下对应的支持情况
增强型表单
HTML5 拥有多个新的表单 Input 输入类型。这些新特性提供了更好的输入控制和验证
| type | 描述 |
|---|---|
| color | 主要用于选取颜色 |
| date | 选取日期 |
| datetime | 选取日期(UTC时间) |
| datetime-local | 选取日期(无时区) |
| month | 选择一个月份 |
| week | 选择周和年 |
| time | 选择一个时间 |
| 包含e-mail地址的输入域 | |
| number | 数值的输入域 |
| url | url地址的输入域 |
| tel | 定义输入电话号码和字段 |
| search | 用于搜索域 |
| range | 一个范围内数字值的输入域 |
HTML5 新增以下表单元素
| 表单元素 | 描述 |
|---|---|
| datalist | 元素规定输入域的选项列表使用 input 元素的 list 属性与 datalist 元素的 id 绑定 |
| keygen | 提供一种验证用户的可靠方法标签规定用于表单的密钥对生成器字段。 |
| output | 用于不同类型的输出比如计算或脚本输出 |
HTML5 新增的表单属性
| 表单属性 | 描述 |
|---|---|
| placehoder | 输入框默认提示文字 |
| required | 要求输入的内容是否可为空 |
| pattern | 描述一个正则表达式验证输入的值 |
| min | 设置元素最小值 |
| max | 设置元素最大值 |
| step | 为输入域规定合法的数字间隔 |
| heigh | 用于image类型input标签图像高度 |
| wdith | 用于image类型input标签图像宽度 |
| autofocus | 规定在页面加载时,域自动获得焦点 |
| multiple | 规定input元素中可选择多个值 |
| form | 可以在form外部的input上面指向某个form,随着form一起提交,方便页面布局 |
| formaction | 用于描述表单提交的 URL 地址。会覆盖 form元素中的action属性 |
| novalidate | 布尔属性,在表单提交时无需被验证 |
| autofocus | 页面加载时自动聚焦到此表单控件 |
视频
<!--video定义视频播放器的容器-->
<!--width 和 height:设置视频播放器的宽度和高度并且增加controls:向用户显示视频播放器的控制按钮-->
<video width="300" height="200" controls>
<!--source定义多个媒体资源,浏览器将选择支持的第一个资源进行播放-->
<!--type支持video/mp4, video/webm, 和 video/ogg-->
<source src="a.mp4" type="video/mp4">
<source src="b.mp4" type="video/mp4">
<!--track字幕,可以定义多个-->
<!--kind规定文本轨道的文本类型-->
<!--srclang规定轨道文本数据的语言。如果 kind 属性值是 "subtitles",则该属性是必需的-->
<!--src文件资源,label规定文本轨道的标签和标题-->
<track src="a.vtt" kind="subtitles" srclang="en" label="标题"/>
<track src="b.vtt" kind="subtitles" srclang="en" label="标题"/>
</video>
视频文件类型各个浏览器支持情况
| 浏览器 | MP4 | WebM | Ogg |
|---|---|---|---|
| Internet Explorer 9+ | YES | NO | NO |
| Chrome 6+ | YES | YES | YES |
| Firefox 3.6+ | NO | YES | YES |
| Safari 5+ | YES | NO | NO |
| Opera 10.6+ | NO | YES | YES |
音频
<!--- autoplay指定音频或视频在页面加载时自动播放-->
<!--- loop指定音频或视频在播放结束后是否循环播放-->
<!--- preload指定是否在页面加载时预加载音频或视频,可设置为 "auto"、"metadata" 或 "none"-->
<audio controls autoplay loop preload="auto">
<source src="horse.ogg" type="audio/ogg">
<source src="horse.mp3" type="audio/mpeg">
<source src="horse.mp3" type="audio/wav">
</audio>
ps:音频和视频都有autoplay、loop、preload属性
音频文件类型各个浏览器支持情况
| 浏览器 | MP3 | Wav | Ogg |
|---|---|---|---|
| Internet Explorer | YES | NO | NO |
| Chrome | YES | YES | YES |
| Firefox | YES | YES | YES |
| Safari | YES | YES | NO |
| Opera | YES | YES | YES |
Canvas绘图
一般用于组合图片,或者在图片上绘制文字,生成二维码,绘制动画效果等,下面是一个简单的例子
<!DOCTYPE html>
<html>
<body>
<!--定义一个空白的画布-->
<canvas id="myCanvas" width="200" height="100" style="border:1px solid red;">
</canvas>
<script>
// 获取Canvas元素的上下文
const canvas = document.getElementById('myCanvas');//通过id获取canvas对象
const ctx = canvas.getContext('2d');//获取2D上下文,用于进行绘图操作
// 绘制矩形
ctx.fillStyle = 'green';//设置填充颜色
ctx.fillRect(10, 10, 150, 80);//fillRect(x, y, width, height)绘制填充的矩形
// 绘制文本
ctx.fillStyle = 'white';//设置填充颜色
ctx.font = '20px Arial';//设置字体样式
ctx.fillText('我要吃烤鸭!', 20, 50);//fillText(text, x, y)在画布上绘制填充文本
// 绘制路径(三角形)
ctx.beginPath();//创建一条路径
ctx.moveTo(10, 80);//moveTo(x, y)创建指定一个坐标
ctx.lineTo(85, 10);//lineTo(x,y)绘制一条从当前点到指定坐标的直线
ctx.lineTo(160, 80);
ctx.closePath();//闭合路径,连接起点和终点
ctx.stroke();//绘制路径的边框
</script>
</body>
</html>
SVG绘图
<svg>
<ellipse cx="150" cy="80" rx="100" ry="50" style="fill:yellow;stroke:purple;stroke-width:2" />
</svg>
ps:svgs是W3C推荐标准,优点有如下几个(可能不全),都是我印象中的,更多的svg内容可以参考svg教程学习,我平时都是要求ui给出svg图片。
图像在放大或改变尺寸的情况下其图形质量不会有所损失
使用 XML 格式定义图形,内容更容易被搜索和识别。
相对png之类的可以更好的被压缩
地理定位Geolocation
//geolocation对象的3个方法
//window.navigator.geolocation {
// getCurrentPosition: fn //用于获取当前的位置数据
// watchPosition: fn //监视用户位置的改变
// clearWatch: fn //清除定位监视
//}
<p id="demo">点击按钮获取您当前坐标(可能需要比较长的时间获取):</p>
<button onclick="getLocation()">点我</button>
<script>
var x=document.getElementById("demo");
function getLocation(){
let success = (position)=>{
console.log('定位时间:',position.timestamp)
console.log('经度:',position.coords.longitude)
console.log('纬度:',position.coords.latitude)
console.log('海拔:',position.coords.altitude)
console.log('速度:',position.coords.speed)
}
let error = (error)=>{
switch(error.code) {
case error.PERMISSION_DENIED:
x.innerHTML="用户拒绝对获取地理位置的请求。"
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML="位置信息是不可用的。"
break;
case error.TIMEOUT:
x.innerHTML="请求用户地理位置超时。"
break;
case error.UNKNOWN_ERROR:
x.innerHTML="未知错误。"
break;
}
}
navigator.geolocation ? navigator.geolocation.getCurrentPosition(success,error):(x.innerHTML="Geolocation is not supported by this browser.")
}
</script>
拖拽API
<p>拖动红色div到矩形中:</p>
<!--ondrop监听拖动结束事件-->
<div id="div1" style="width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<!--draggable开启可被拖动,ondragstart监听拖拽开始事件-->
<div id="drag1" style="background:red;" draggable="true" ondragstart="drag(event)">
今天吃了大份的猪脚饭啊
</div>
<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>
拖拽API事件
| 拖动生命周期 | 属性名 | 描述 |
|---|---|---|
| 拖动开始 | ondragstart | 在拖动操作开始时执行脚本 |
| 拖动过程中 | ondrag | 只要脚本在被拖动就运行脚本 |
| 拖动过程中 | ondragenter | 当元素被拖动到一个合法的防止目标时,执行脚本 |
| 拖动过程中 | ondragover | 只要元素正在合法的防止目标上拖动时,就执行脚本 |
| 拖动过程中 | ondragleave | 当元素离开合法的防止目标时,就执行脚本 |
| 拖动结束 | ondrop | 将被拖动元素放在目标元素内时运行脚本 |
| 拖动结束 | ondragend | 在拖动操作结束时运行脚本 |
WebWorker
web worker 是运行在后台的非阻塞性质的 JavaScript,不会影响页面的性能,更好的解释是,你可以使用web worker提供的一种简单的方法来为web内容在后台线程中运行脚本,这些线程在执行任务的过程中并不会干扰用户界面,并且这个worker的数量是有上限的一般取决于cpu的内核数量如果是8核cpu,那最多就创建8个最佳,否则也是会影响性能的。 主要优势是
-
并行处理:可以同时执行多个任务,而不会相互阻塞,特别是在多核CPU上。
-
性能提升:对于密集型任务,Web Workers可以提高应用程序的整体性能和响应速度。
-
用户体验改善:主线程(通常是UI线程)不会因为需要执行复杂计算而被阻塞,因此应用程序仍然可以响应用户操作。
//work.js
var i=0;
function timedCount(){
i=i+1;
postMessage(i); //通过 postMessage发送结果到前端(比如下载进度百分比,上传进度百分比等)
let time = setTimeout(()=>{
time = null
timedCount()
},500);
}
timedCount();
//使用的时候
let works_a=new Worker("demo_workers.js");
let works_b=new Worker("demo_workers.js");
works.onmessage = function (event) {
//接收Worker的回传信息
console.log(event.data)
}
//停止works
works.terminate();
WebStorage离线存储
离线存储允许web应用在用户的设备上本地保存数据,这样即使在没有网络连接的情况下,用户也能加载和使用应用。离线存储的目的是提高应用的性能和可用性,得到更好的用户体验。目前常用的有LocalStorage、SessionStorage和IndexedDB、Cookie
LocalStorage、SessionStorage、IndexedDB、Cookie的区别
-
LocalStorage:
- 用于长期存储数据,数据没有过期时间,除非主动删除数据,否则数据永远不会消失。
- 存储容量较大,一般在5MB左右。
- 只能存储字符串,因此需要将对象JSON序列化。
-
SessionStorage:
- 用于临时存储数据,数据仅在页面会话期间存在,页面关闭则数据消失。
- 和 LocalStorage 类似,但它的作用域限于单个页面会话。
- 存储容量和 LocalStorage 相似,也主要用于存储字符串数据。
-
IndexedDB:
- 是一个低级API用于客户端存储大量结构化数据,包括文件/二进制大对象。
- 支持事务,可以存储和操作大量数据。
- 存储容量比 LocalStorage 和 SessionStorage 大得多。
- 允许你创建索引来高效查询数据。
-
Cookie:
- 按照域名存储,你在哪一个域名下存储的内容, 就在哪一个域名下使用, 其他域名都用不了, 和资源路径地址没有关系。
- 存储大小有限制,4KB 左右或者50 条左右。
- 时效性,默认是会话级别的时效性(关闭浏览器就没有了),可以手动设置。
- 请求自动携带,当你的 cookie 空间里面有内容的时候,只要是当前域名下的任意一个请求, 都会自动携带 cookie 放在请求头里面, cookie 里面有多少自动携带多少,没有就不会携带了。
- 安全性不高,不建议存储敏感数据 示例
<!-- 保存设置按钮 -->
<button onclick="saveSettings()">保存到LocalStorage</button>
<button onclick="saveSessionSettings()">保存到SessionStorage</button>
<button onclick="saveIndexedDBSettings()">保存到IndexedDB</button>
<!-- 读取设置按钮 -->
<button onclick="loadSettings()">从LocalStorage读取</button>
<button onclick="loadSessionSettings()">从SessionStorage读取</button>
<button onclick="loadIndexedDBSettings()">从IndexedDB读取</button>
<!-- 显示设置的区域 -->
<div id="settings"></div>
<script>
// LocalStorage 示例
function saveSettings() { // 保存设置到LocalStorage
localStorage.setItem('favoriteChampion', '炸鸡');
localStorage.setItem('resolution', '烤串');
console.log('设置已保存到LocalStorage');
}
function loadSettings() {
// 从LocalStorage读取设置
const favoriteChampion = localStorage.getItem('favoriteChampion');
const resolution = localStorage.getItem('resolution');
document.getElementById('settings').innerText = `LocalStorage - 最喜欢的食物是: ${favoriteChampion}和 ${resolution}`;
console.log('从LocalStorage读取设置');
}
// SessionStorage 示例
function saveSessionSettings() { // 保存设置到SessionStorage
sessionStorage.setItem('sessionFavoriteChampion', '薯条');
sessionStorage.setItem('sessionResolution', '汉堡');
console.log('会话设置已保存到SessionStorage');
}
function loadSessionSettings() { // 从SessionStorage读取设置
const sessionFavoriteChampion = sessionStorage.getItem('sessionFavoriteChampion');
const sessionResolution = sessionStorage.getItem('sessionResolution');
document.getElementById('settings').innerText = `SessionStorage - 最喜欢的食物是: ${sessionFavoriteChampion}和 ${sessionResolution}`;
console.log('从SessionStorage读取设置');
}
// IndexedDB 示例
var db;
// 打开数据库
var request = indexedDB.open('LoLSettingsDB', 1);
request.onerror = function(event) { // 处理打开数据库时的错误
console.log('打开IndexedDB时发生错误。');
};
request.onupgradeneeded = function(event) { // 数据库升级或首次创建时执行
db = event.target.result;
if (!db.objectStoreNames.contains('settings')) {
var objectStore = db.createObjectStore('settings', { keyPath: 'id' });
objectStore.createIndex('favoriteChampion', 'favoriteChampion', { unique: false });
objectStore.createIndex('resolution', 'resolution', { unique: false });
}
};
request.onsuccess = function(event) { // 成功打开数据库
db = event.target.result;
console.log('IndexedDB成功打开');
};
function saveIndexedDBSettings() { // 保存设置到IndexedDB
var transaction = db.transaction(['settings'], 'readwrite');
var objectStore = transaction.objectStore('settings');
var userSettings = { id: 'food', favoriteChampion: '鸡腿', resolution: '鸭腿' };
var request = objectStore.put(userSettings);
request.onsuccess = function(event) {
console.log('食物设置已保存到IndexedDB');
};
request.onerror = function(event) {
console.log('保存设置到IndexedDB时发生错误');
};
}
function loadIndexedDBSettings() { // 从IndexedDB读取设置
var transaction = db.transaction(['settings']);
var objectStore = transaction.objectStore('settings');
var request = objectStore.get('food');
request.onsuccess = function(event) {
if (request.result) {
document.getElementById('settings').innerText = `IndexedDB - 最喜欢的食物是: ${request.result.favoriteChampion}和 ${request.result.resolution}`;
console.log('从IndexedDB读取食物设置');
} else {
console.log('在IndexedDB中未找到食物设置');
}
};
request.onerror = function(event) {
console.log('从IndexedDB读取时发生错误');
};
}
</script>
WebSocket长连接
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
//web_socket_utils.js
export const WebSocketTest =(call_back)=>{
if ("WebSocket" in window){
//浏览器支持 WebSocket 打开一个 web socket
const ws = new WebSocket("ws://localhost:9998/echo");
ws.onopen = function()
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("发送数据");
};
ws.onmessage = function (evt)
{
call_back(evt.data)
};
ws.error = function (evt)
{
call_back(evt.data)
};
ws.onclose = function()
{
// 关闭 websocket
};
ws.onopen()
}else{
// 浏览器不支持 WebSocket
}
}
//使用WebSocketTest的时候
import {WebSocketTest} from './web_socket_utils'
let get_server_data = (data)=>{
//socket返回的数据data
}
WebSocketTest(get_server_data)
HTML5移除的标签
1.样式标签:不再推荐使用一些样式标签,如<big>、<basefont>、<big>、<center>、<font>、<s>、<tt>、<u>、<strike>等,应使用CSS来设置样式。
2.部分浏览器支持的元素:<applet>、<bgsound>、<blink>、<marquee>、<object>:HTML5不再推荐使用<applet>和<object>标签来嵌入Java小程序或其他外部插件,而是鼓励使用<embed>、<video>、<audio>等标签。
3.对可用性产生负面影响:<frameset>、<frame>、<noframes>:html5中不支持frame框架,只支持iframe框架,推荐使用<iframe>或其他技术来实现相同效果。
- 其他标签:
- 废除
<menu>标签,推荐使用无序列表<ul>替代 - 废除
<rb>,使用<ruby>替代 - 废除
<acronym>使用<abbr>替代 - 废除
<dir>使用<ul>替代 - 废除
<isindex>使用<form>与<input>相结合的方式替代 - 废除
<listing>使用<pre>替代 - 废除
<xmp>使用<code>替代 - 废除
<nextid>使用<guids>替代 - 废除
<plaintex>使用“text/plian”(无格式正文)MIME类型替代
总结
梳理了HTML5的知识点,如果有不对的地方也希望大家指正。