HTML 5 是什么?
一直在听大家说 H5 好,H5 妙,H5强大。那么你是否真正理解 H5 是什么,H5 强大的地方有在哪里?
前言
作为程序员,技术的落实与巩固是必要的,因此想到写个系列,名为 why what or how 每篇文章试图解释清楚一个问题。
这次的 why what or how 主题:现在几乎所有人都知道了 HTML5 ,那么 H5 到底相比于 HTML4 有什么区别呢?
升级版?标准版!
HTML5 做为 HTML 标准的第 5 版,于 2014 年发布,相信关注过 HTML5 的发展史的朋友都知道该版本是 WHATWG 和 W3C 握手言和后诞生的,是 W3C 组织与浏览器厂商相互妥协的结果,其中的绝大部分规范都由 WHATWG 组织所制定,之后由 W3C 采纳并入标准中。
但 HTML5 是 HTML4 的升级版吗?
是、也不是,如果以版本的更迭来看,HTML5 确实是在 HTML4 之后诞生,但是 HTML5 本质上却已经不同于 HTML4 了。
相信大家目前都还留有对 HTML4 的些许印象,在写 HTML4 时需要加一段特殊的说明来声明文档类型的:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
该段声明说明了该文档基于 http://www.w3.org/TR/html4/strict.dtd 规范,从一个侧面来看,该文档仅仅是符合这种规范的文本而已,而这种规范被称为 SGML(标准通用标记语言)。
接着在来看看 HTML5 的文档声明:
<!DOCTYPE html>
简简单单,清晰明了,说明该文档是 HTML 文档,并没有基于规范。
从浏览器的角度来对比,HTML5 之前的版本,浏览器必须要从 W3C 官网上获取规范文件,才能解析文档,而 HTML5 文档可以被浏览器直接识别。
这些角度都表明了,HTML5 之前的 HTML 是 SGML 规范的一种实现,而 HTML5 却是原原本本的 HTML,有自己的规范,因此 HTML5 可以认为是一种新的标准,该标准诞生于 HTML4,却不是 HTML4 的升级。
但不管是基于 SGML 的 HTML 版本,还是 HTML5 版本,其语法内容都差不多。因此也不需要过多的纠结在这个问题上,实用主义者,能用好用就行~
语义化
在看过 什么是 CSS? 之后,大家应该知道样式的发展过程中经历了一个用标签表达样式的阶段,该阶段产生了一些样式标签,比如 <font> <center> <big> 等。但 HTML5 提出结构和样式分离,样式表达在 Css 内,而 HTML 负责结构,样式标签正式宣告脱离舞台,在 HTML5 的规范下,这些标签正式被废除,一些代表结构的标签被提出并规范。
结构化,样式脱离的 HTML 文档,极大提高了文档的表达力,不管是机器还是人类都能更快的理解文档的结构,这种文档就被称为语义化文档。
语义化主要体现在以下几个方面:
结构标签
写过 HTML5 的都知道大概有哪些标签新加了进来,这里大致罗列一下
| 标签 | 释义 | 
|---|---|
section | 
代表文档组成的一部分,应该与 h[1-6] 结合使用,表示文档结构。 | 
article | 
代表文档的独立内容区域,该区域内容为博文、报纸文章等内容。 | 
main | 
代表文档的主要内容区域。 | 
aside | 
代表与内容主题略有相关的区域。 | 
header | 
代表该文档的介绍性区域。 | 
footer | 
代表该文档的页脚,通常用于存放版权,作者等信息。 | 
nav | 
代表文章导航区域。 | 
figure | 
代表该区域内有多媒体内容,通常多媒体标签作为该标签的子元素。 | 
template | 
模板区域,可以被 JavaScript 所使用。 | 
video | 
通过该标签可以引用视频,该标签代表视频可以显示的区域。 | 
audio | 
通过该标签可以引用音频,该标签代表音频可以显示的区域。 | 
track | 
该标签为 video 提供了字幕。 | 
mark | 
代表需要特殊注意的内容区域。 | 
progress | 
该区域代表某项任务的进度。 | 
meter | 
该区域代表某项内容的使用量,比如 CPU 使用量等。 | 
time | 
该区域代表时间。 | 
canvas | 
该区域代表可以被 JavaScript 所控制的画布。 | 
可能有些朋友会纳闷,这些东西其实吧,也不是那么的重要,用 div + css 也都能实现,而且各个浏览器上表现的还都一致,还不用考虑兼容问题。那么为什么这里还提呢?
试想一个问题?
如果你是浏览器,或者说是解析 HTML5 文本内容的程序,会怎么看待 HTML4 与 HTML5 ?
首先第一个需要解决的问题:显示页面,两者都能解析,生成树状结构,并成功的显示页面,这也是大部分用户所需要的。在这方面两者平局,HTML5 没有任何的优势。
那么现在第二个问题,识别该文档,这或许不是大部分用户的需求,但小部分用户并不意味着人数少。
相信大部分朋友都有使用搜索引擎的习惯,那么搜索引擎是如何帮你找到这个网页的呢?
搜索引擎通过适当的策略解析通过爬虫抓取到的网页内容,将该文章进行分类,通过用户给的搜索词进行匹配,最终将结果呈现给用户,爬虫的解析策略,面对 HTML4 时,需要识别出特定的 div 而这个特定的 div 该如何去找呢?经验?特定字符串?面对 HTML4 ,只能得到一个个的 div 而哪个 div ,emmm...  不好找。面对 HTML5 呢?程序从结构就能大致理解文档的结构,进而识别出该篇文章的大体内容。
问题二可以简单认为:我们需要生成文章大纲,一篇文章可以有几部分的内容组成,而规范这些内容的就是大纲,相信有写过文章的都知道大纲的作用,可以清晰的表达出内容,那么 HTML4 呢,一堆 div 分不清哪个是主体,哪个是次要,但 HTML5 呢,结构清晰,解析程序也能很快的生成文档的大纲。
大纲只能用在搜索引擎吗?并不是,阅读设备就很需要大纲生成目录,无障碍设备可以识别到文档的主体内容等等。
看到这里,相信大家对于语义化标签的重要性也有了了解,使用成本几乎为 0,但文档的清晰程度却上了一个层级,干嘛不用呢?
新增的表单类型
表单类型(type)代表了该表单内容的类型,新增了以下几个
telsearchurlemaildatetimenumberrangecolor
新的标签属性
| 属性 | 示例 | 含义 | 
|---|---|---|
target | 
<base target="..."> | 
base 标签新增 target属性,虽然之前已经被广泛的使用了。 | 
charset | 
<meta charset="utf-8"> | 
meta 标签新增 charset 属性,规范文档所使用的字符集。 | 
placeholder | 
<input placeholder="..."> | 
可输入的表单元素新增 placeholder 属性,代表默认内容。 | 
form | 
<input form=1> | 
表单元素新增 form 属性,代表关联的 form 表单,而不需要在 form 标签内。 | 
contenteditable | 
<div contenteditable> | 
代表该元素可编辑。 | 
data-* | 
<div data-a="..."> | 
与该元素相关联的数据,可在 JavaScript 中获取。 | 
以上为 HTML5 语义化的具体呈现,希望大家拥抱并使用 HTML5 的新标签。
多媒体
HTML5 的上一代标准 HTML4 于 1999 年发布,当时互联网还处于图文混排的时代,通讯也不是很发达,数据的交互受限于网速,但是近 20 年来数据通讯的高速发展图文混排已经不能满足用户的需求了,由于浏览器并不支持视频促成了 Flash/ActionScript 的发展,但是由于 Flash 的繁琐(需要装插件)以及安全问题,Apple 拒绝使用 Flash,之后各大浏览器厂商也开始重视 Flash 的安全问题,提出了多媒体标签,直到 HTML5 规范化了多媒体应用。
相关多媒体标签
建议查看英文的相关文档,中文的翻译文档好像还没有及时跟进。
除了多媒体标签的更新,这里同时还列举一些与显示相关的内容:
- Canvas
 
画布,可以使用 JavaScript 在该元素规定的区域内进行绘画,文档说明。
- WebGL
 
光栅化的图片绘画引擎,主要用于 3D 制作,文档说明,以及WebGL 理论基础
- Camera API
 
通过Camera API,你可以使用手机的摄像头拍照,然后把拍到的照片发送给当前网页。
- SVG
 
现在可以直接在 HTML5 文档中写 SVG(可缩放矢量图形),一种用于描述基于二维的矢量图形的,基于 XML 的标记语言。文档说明。
- MathML
 
MathML(Mathematical Markup Language),是一种基于 XML 的标记语言,用以描述数学公式,但目前浏览器的支持力度有点低。具体可以查看文档说明
通信
HTML5 之前,JavaScript 只能通过 XMLHttpRequest 与后端程序进行交互,随着 HTML5 标准的提出,前端可以使用各种各样的姿势与后端进行沟通,数据的交互变的简单,灵活。
fetch
XMLHttpRequest,虽然在实际开发中几乎很难使用到它,但是对于它的封装库我们却经常使用,比如 axios $.ajax 。虽然说封装的库降低使用成本,但源头是复杂的,而且 XMLHttpRequest 是基于回调的异步模式,虽然 axios 进行了 Promise 化,但毕竟不是原生支持。因此一个基于 Promise 的请求 API 于 HTML5 标准内提出:fetch。
一个简单的 fetch 例子
fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });
fetch 支持两个参数,
- 资源地址
 - 请求参数,用于设置请求方式,请求头,请求体等内容,一个 JavaScript 对象。
 
学习资源:
WebSocket
在 HTML5 出现之前,做一个实时聊天的 web 项目是极其困难的,由于之前的版本仅支持浏览器主动向服务器进行发送内容,必须先有请求才能有服务器响应的数据,简单的来说服务器并不能主动将数据提交给客户端。
面对这些需求,大家的做法通常是轮询,通过前端设置一个定时器,每隔固定的时间去请求服务器资源,即使服务器并没有发生数据更新。这浪费了极大的服务器资源,那么有没有一种方式支持服务器推送呢?
有!WebSocket 是 HTML5 新增的一种协议,目的是在浏览器和服务器之间建立一个双向数据通道,浏览器可以推送数据到服务端,服务端也可以推送数据到客户端。WebSocket 对于前端来说仅是一个简单的 API,最重要的是服务端的支持。
WebSocket 的客户端代码示例
// 创建链接
const socket = new WebSocket('ws://localhost:8080');
// 链接开启事件
socket.addEventListener('open', function (event) {
    // 向服务端推送数据
    socket.send('Hello Server!');
});
// 服务端推送事件,event.data 即为服务端推送的数据
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});
至于服务端如何实现,不同的语言有不同的实现,比较出名的是 Node 下的 Socket.IO,如果担心服务端语言实现困难,不妨用 Node 搭建中间层,使用 Node 进行与客户端的沟通,并将数据交由服务端程序处理。当然也可以查看 MDN 的文章:编写 WebSocket 服务器
一些资源
- WHATWG Web sockets
 - websocket.org HTML5 WebSocket
 - MDN WebSockets
 
EventSource
fetch 实现了请求的 Promise 化,WebSocket 实现了双工通信,那么 EventSource 又是什么?
简单的来说,EventSource 实现了服务端对客户端的单向通信,可以理解为客户端是订阅者,服务端是内容发布者,也就是发布订阅模式的实现。
一个简单的例子
// 开始订阅
var evtSource = new EventSource('sse.php');
// 服务端发布数据回调
evtSource.onmessage = function(event) {
    // event.data 即为服务端发布的数据
    console.log('Message from server ', event.data);
}
同样的前端代码很简单,服务端需要实现该通信方式需要有一定的成本。具体可以查看一下文档
- WHATWG EventSource
 - MDN EventSource
 - see.php 编写
 
WebRTC
WebRTC(网页即时通信),是一个支持网页浏览器进行实时语音对话或视频对话的 API。由于该 API 目前并未纳入标准中,这里就不过多的深入了,可以通过以下文档进行了解:
- MDN WebRTC API
 - W3C WebRTC 1.0
 
存储
在 HTML5 出现之前,前端开发者仅能通过 cookie 来存储用户在不同页面之间跳转的数据,但使用 cookie 来存储数据其意义上是不对的,不能说 cookie 可以在同域名下通用,就让它来携带各种各样的数据,cookie 应该是用来标志用户身份的。HTML5 出现之后,规范了数据的存储,cookie 也回到了原始的用途。
storage
相信大家对于该 API 已经熟悉的不能在熟悉了,storage 分为两部分,sessionStorage 与 localStorage,拥有同样的方法:
setItemgetItemremoveItemclear
localStorage 会将数据永久的存储下来(当然用户可以主动清除),sessionStorage 中设置的数据当用户关闭页面后会清除。
- WHATWG Web storage
 - MDN Storage
 
IndexedDB
小型的数据有 storage 已经够用,那么浏览器端如何进行大量数据的存储呢?IndexedDB 就是 HTML5 给出的答案。IndexedDB 是浏览器内置的一个数据库,用于存储结构化数据。但这个数据库是异步存取数据的,说实话有点难使用,如果使用他,那基本上所有的代码都在 then 方法里了。考虑使用吧。
可以通过使用 IndexedDB进行学习和使用。
DOM 的更新
query
querySelector使用CSS选择器进行选择元素,仅选取匹配元素中的第一个。querySelectorAll使用CSS选择器进行选择元素,返回所有匹配的元素。
data-*
可以通过在标签上使用 data-* 设置与元素绑定的数据,JavaScript 可以通过 dataset 获取或设置。
<p id="title" data-text="hello"></p>
const p = document.querySelector('#title');
p.dataset.text // hello
元素添加
prepend在规定标签的最前面添加元素append在规定标签最后面添加元素
element 相关
firstElementChild获取规定标签中的第一个子元素lastElementChild获取规定标签中的最后一个子元素previousElementSibling获取前一个兄弟元素nextElementSibling获取后一个兄弟元素
类名操作
Node.classList.add添加类名Node.classList.remove移除类名Node.classList.toggle切换类名Node.classList.contains检测是否有类名
拖拽
在 HTML4 中想实现元素拖拽,我们需要这样一个过程,获取元素,设置元素定位,与需要被拖入的元素进行碰撞检测,检测完成后进行拖入操作。在 HTML5 中规范了这一过程。
相关事件
dragstart设置在拖动元素上,标志拖动开始dragenter设置在拖入元素上,标志有元素开始拖入到该元素内dragover设置在拖入元素上,标志元素完全拖入该元素dragleave设置在拖入元素上,标志元素即将离开该元素drop设置在拖入元素上,标志拖动元素放下
拖动元素与拖入元素可以通过 e.dataTransfer.getData(xxx) e.dataTransfer.setData(xxx, xxx) 进行数据交互。
MutationObserver
MutationObserver 字面意思为变动观察器,用来观察文档节点的变动。相关文章
最后
DOM 中,接触最多的也就这些内容了,更为详细的内容可以通过DOM STANDARD查看。
BOM 的新增
在什么是 JAVASCRIPT中,我们提到过 BOM 并没有相关的标准去规范它,HTML5 中一些没有归到 DOM 中 API 更新就归到这。
Web Workers
我们都知道 JavaScript 是以单线程的形式运行在客户端,这就避免不了当进行大规模的数据运算时所带来的堵塞问题,为解决这一问题 HTML5 提出了 Web Workers 的概念,并最终纳入规范。使用 Web Workers 可以将与页面渲染无关的数据运算代码放入另一个线程,线程间通过 postMessage 发送数据,通过 onmessage 回调获取数据。
一个简单的例子
// workers.js
let i = 0;
function timedCount() {
    i = i + 1;
    postMessage(i);
    setTimeout(timedCount, 500);
}
timedCount();
const w = new Worker("workers.js");
w.onmessage=function(event){
    console.log('Message from worker ', event.data);
};
相关资源:
目前大火的 PWA 应用,其核心 Service Worker 其实也是 Web Workers 的一个实现。 Service Worker 使用编程的方式来进行资源的缓存,与后台进行数据同步等内容。虽然该内容已在不少的浏览器上实现,但标准仍在草案阶段,等出标准规范在详细介绍。
相关资源
- W3C Service Workers
 
History
在 HTML5 之前,前端开发者只能通过 history 对象进行前进后退的动作,但却不能在不刷新当前页面的情况下进行 url 修改,在 HTML5 之前,单页应用仅能通过 hash 模式进行路由管理,但通过 HTML5 新提出的 history API ,单页应用就能像正常应用那样管理页面的 url 了。通过以下 3 个方法即可:
pushState不刷新页面导航到指定URL并产生历史记录。replaceState不刷新页面并将页面当前URL替换为指定URL,不产生历史记录。popstate事件 在当前页面点击返回时,window 对象会触发该事件,可以使用 addEventListener 进行监听。
相关资源
requestAnimationFrame
通知浏览器,在下一次重绘之前调用指定 callback。由于重绘与屏幕刷新率挂钩,因此该 API 的调用也与屏幕刷新率挂钩,可以使用该 API 进行一些复杂运算的分解,将任务放在每次刷新的间隔中,这样就不会产生屏幕要刷新了但浏览器却没及时绘制出页面的尴尬情况出现,使得页面显示平滑,不掉帧。因此该 API 的出现促进了 Canvas 的发展,而 Canvas 的发展又促进了页游的发展。
requestAnimationFrame(callback)
如果想实现类似定时器的效果,只需要在 callback 中再次调用 requestAnimationFrame 即可。
相关资源
全屏 API
Element.requestFullscreen()将当前元素全屏展示Document.exitFullscreen()取消全屏显示
相关资源
- MDN 全屏 API
 
获取地理位置信息
navigator.geolocation.watchPosition()监听地理位置信息,当发生改变时,触发回调navigator.geolocation.getCurrentPosition()获取地理位置信息
以上两方法都需要传入,成功回调和失败回调,分别为参一和参二。
相关资源
- MDN 使用地理位置定位
 
CSS3
在 什么是 CSS? 中,我们提到过,CSS 标准被 W3C 采纳,并最终成为 HTML 标准的一部分,因此 CSS 内容的更新也算是 HTML5 更新的一部分。
这部分单独说吧。
总结
惯例,问几个问题
HTML5涵盖了那几方便面的更新?- 通信方式有什么新姿势?
 - 语义化的体现,以及语义化的作用?
 js如何更好的处理数据而不影响页面渲染?- 单页应用的 
history是基于那些api实现的? 
谈谈感受
随着 HTML5 的更新,前端再也不是切图仔,浏览器也开始做为了一个 GUI 工具存在,而不仅是为了展示页面。相信随着技术的发展,当通讯延迟降低到一定程度后,乔帮主的设想 all in browser 将会成为现实。
参考
最后的最后
该系列所有问题由 minimo 提出,爱你哟~~~