前言
迷茫的时候,卷就是最好的选择;毕竟,与人斗其乐无穷。
本节主要包括以下部分的查漏补缺
- HTML5 特性
- 各种特性概念介绍;如何使用;掰头一下原理及优缺点;应用及最佳实践的思考
HTML5 特性介绍
话说,HTML5 发布都快 20 年了,其中增加的一些内容实在是很陈旧的东西了,但所谓温故而知新,知识总是常学常新的~~~
HTML5 新增特性整理
- 语义化标签
- 表单增强
- Web Storage
- Web Worker
- canvas 图形绘制
- SVG 矢量图形
- 音视频处理
- 地理定位
语义化标签
HTML5 引入了一系列的语义化标签,用来让文档结构更加清晰,并帮助搜索引擎更好的理解网页
以上是一张使用 HTML5 语义化标签实现的页面图,它不再是 div 嵌套的形式
为什么要使用语义化标签
div 布局玩的好好的,为啥非要整这么些个语义化标签?这就不得不说说语义化标签的优点了
- 在没有 css 时,页面也能呈现较好的内容结构
- SEO 友好,爬虫依赖标签来确定上下文及关键字的权重
- 屏幕阅读器友好,视障人士的福音(事实上国内网站几乎就不考虑这个,他们觉得没事听啥网页,哎~)
- 可维护性,可读性;看到对应的标签就知道大致包含的内容了,维护起来自然也方便许多
header
header 元素代表页面、section、article 的头部
以掘金网首页为例,具有两个 header 元素,分别是公用的大头部和列表头
最佳实践:
- header 允许有多个,但一般情况下,只对页面头部或 section 头部使用 header 元素
- 对于可以使用 h1-h6 实现的简单头部,不需要使用 header 标签
补充一点,也不要滥用 h 标签,一个页面最好有且只有一个 h1;h2-h4 不要超过 5 个,只在内容是关键词时使用;避免使用更低层次的标题 h5、h6;如果只是单纯的加粗,可以使用 strong 标签;这在 SEO 中很重要,因为标题会影响关键字和权重
footer
footer 元素代表页面、section、article 的底部
页面级的 footer 一般会包含一些版权信息、备案信息、友情链接、文档说明
最佳实践:
- footer 允许有多个,一般情况下,只会在页面级别使用
- 有时也会在 article、section 底部使用,如一篇文章, 底部有评论、点赞、分享功能,可以放到 footer 中(如微博的文章)
nav
nav 元素用来包含与当前页面主要导航相关的元素
最佳实践:
- 不要滥用 nav,nav 应该用来包含主要导航;不是链接到其他地方就使用 nav,如第三方友链、广告;这些使用 ul 就可以了
- 页面交互性搜索,个人信息等内容,应该放到 nav 中,如上掘金网首页的 nav
- 移动端下,浏览器可能将其转换为滑动菜单
以上是 vue 文档移动端下抽屉式导航
效果,它会在页面的一侧隐藏起来,用户可以通过点击屏幕边缘的按钮或图标来展开和收起这个菜单;当然这是网站自己实现的,而 nav 本身在移动端就可能被解析为抽屉式导航;
为了保证各浏览器的兼容性,最好是通过媒体 fixed 布局的形式来实现移动端下 nav
main
main 元素用来包含页面主要元素
最佳实践
- main 一个页面只能有一个,一般放在 header 和 footer 之间
- mian 代表页面的核心区域,内部可能会包含 section、article 的内容;但不能被他们包含
article
article 元素表示一篇文章、新闻报道、博客帖子、评论、回复或其他类似内容
最佳实践
- 尽可能避免将多个 article 元素嵌套在一起,以免混淆文档的层次结构;如果需要请在内部使用 section
- 只有当某个部分具有足够的独立性和完整性时,才适合使用 article 元素;比如文章描述是段落文本,它只适合作为 article 的一部分,而不应该是一个 article
aside
aside 用来表示与主内容有关,可以被视为从属关系的内容
section
当内容存在明显逻辑分隔的时候,使用 section 来分割;如介绍、目录、结论等,可以分割为多个 section
最佳实践
- section 提供一个 id,用来锚点
time
time 元素用来表示日期、时间信息
最佳实践
- 所有与时间相关的信息,都应该使用 time 元素;比如倒计时、日期等
- 必须包含 datetime 属性,以便阅读器识别日期时间格式;datetime 应当符合 ISO8601 标准格式,如 YYYY-MM-DDTHH:MM:SSZ 或 YYYY-MM-DD;
掘金网的 time 元素,挠头?datetime 属性还包含了毫秒数???
github 甚至使用 shadowDOM 实现了一个自定义标签,表示所有与时间相关的信息,如上,提交时间是 13 hours age
使用的是 relative-time 自定义标签;不得不服~
mark
mark 元素用来高亮搜索关键词
最佳实践
- mark 元素默认具有黄色背景和下划线样式,可以通过 CSS 重置
- mark 只能用来包裹文本,不能包裹其他标签
- em 也用来进行文本强调,比如百度搜索,关键词标红,就是通过 em 实现的;灵活运行两者
兼容性
2016 年至今,老选手了,兼容性这一块杠杠的,可以放心使用;当然,为了确保万无一失,可以通过 css hack 的形式对不支持的浏览器进行兼容
css
header, footer, main {
display: block;
}
尽管语义化标签兼容性很好,就算不兼容,也很容易 hack;然而事实上,大多数网站也还是 div 套娃的形式;我想这主要是历史遗留和开发人员技术栈、开发习惯等原因造成的;值得欣慰的是越来越多的网站正在逐渐采用语义化标签,这是无数前端努力的成果~
表单增强
HTML5 对表单元素进行了一系列的增强,大大提升了用户体验和开发者效率,改善了网站的安全性
input 表单的 type 拓展
为了让开发者更加方便地创建各种类型的表单控件,同时也能更好地满足用户的输入需求,HTML5 对 input 的 type 进行了拓展,主要有以下常用类型
- color,色值选择器
- date、datetime、month、week、time 等时间相关的选择;在对样式要求不高时,可以作为选择
- email 地址输入域
- search 搜索域,与 datalist 配合使用
- tel 电话号码输入
- number 数字输入
- range 范围选择器
maxlength 对于 number 不生效问题
经常会遇到限制某个输入框的最大长度的需求,比如一个要求输入手机号的输入框:
<input type="text" placeholder="请输入手机号码" maxlength="11" />
但是 text 有一个不好的体验,就是获取焦点后弹出的输入法是默认拼音的那种,不太适合此处要求纯数字的需求。那么自然会想到改为 number,改为后你会崩溃, 竟然发现 maxlength 属性不起作用了,可以无限地输入...
后面去试了下 tel 类型,发现 maxlength 属性又变有效了;着实让人牙疼~~~
兼容性的做法是在输入值变化时,进行判断截取
<input type="number" oninput="if (value.length > 11 ) { value = value.slice(0, 11) }" />
上述办法同样适用兼容性处理限制用户输入数字、字母、最大最小值等;当然为了保险起见,后台也必须进行一致限制,以防止非法数据插入数据库
色值选择
color 选择器常会作为隐藏点击元素,展示为 button 的形式来实现色值选择;选择后通过 dom.value 即可拿到色值
这就和一些 UI 组件的 Upload 一样,如 element,采用的是 button 覆盖在隐藏的 file input 之上的方式实现
range
range 作为天然的具有拖拽的范围选择,样式稍作修改,就是一个完美的进度条;同时结合 css 可以用来实现如评分星数、中高低密码强度等效果;非常好用
新增表单元素
- datalist,输入域的选项列表,通常是 search input 的 list 属性与 datalist 的 id 关联
- output,用来计算或动态脚本
datalist 使用
html
<input type="search" list="searchList">
<datalist id="searchList">
<option>前端</option>缺失缺失缺失
<option>HTML</option>
<option>JavaScript</option>
</datalist>
很快捷的就实现搜索联想功能;我查看了包括 github、淘宝、京东、百度、谷歌等网站;并没有任何站点有使用它来做搜索功能;datalist 与 input 绑定,样式控制确实有诸多不便,同时搜索定制化效果比较多,div、ul 模拟反而更方便
但是,这并不影响 datalist 的使用,因为它和其他类型的 input 也能产生较好的联动效果
datalist 与 color 配合;配置推荐色值
html
<input type="color" />
<input type="color" list="redColors" id="colors" />
<datalist id="redColors"></datalist>
datalist 与 range 配合;分配刻度
ini
<input type="range" list="tickmarks" min="0" max="100" id="tick" name="tick" />
<datalist id="tickmarks">
<option value="0"></option>
<option value="10"></option>
<option value="20"></option>
<option value="30"></option>
<option value="40"></option>
<option value="50"></option>
<option value="60"></option>
<option value="70"></option>
<option value="80"></option>
<option value="90"></option>
<option value="100"></option>
</datalist>
总结就是,datalist,除了和 search 配合,其他时候都挺好用,属于不务正业了是~
新增表单属性
- placeholder 用来提示用户输入
- required 必填
- min、max 最大值最小值,一般与 number 类型的输入域配合使用
- pattern 正则验证输入的值
- autofocus 自动聚焦,不再需要通过 js focus 来聚焦
设置了 min、max 输入框后面会出现向上向下箭头,切换时,值会在 min-max 之间变化;但是,输入是可以随意输入的,没错,你需要结合 oninput 事件限制用户输入,闹呢~
Web Storage
HTML5 新增了 localStorage、sessionStorage 用来缓存数据;使用时非常简单
js
localStorage.setItem("name", "value");
localStorage.getItem("name"); // => 'value'
localStorage.removeItem("name");
localStorage.clear(); // 删除所有数据
sessionStorage.setItem("name", "value");
sessionStorage.setItem("name");
sessionStorage.setItem("name");
sessionStorage.clear();
与 cookie 对比
在这之前,我们一般通过 cookie 来存储数据,限制非常严重
- cookie 只有 4k,而 Web Storage 约为 5M
- cookie 中的信息会发送到服务器,过大会造成负担;老项目的性能优化,cookie 的缩减是很重要的一项
- 操作简单,cookie 是一串字符串,每次都需要从字符串中解析,尽管我们可以封装 cookieUtils,但 Web Storage 则天然具有简单的 API
- 查询快,如上 cookie 需要解析字符串,而 Web Storage 则使用散列存储,快速查询
localStorage 与 sessionStorage
浏览器可以通过 localStorage 与 sessionStorage 安全地存储键值对;内容会保存在同一个源下的 Storage 对象中
localStorage 中存储的数据除非主动清除,如清除浏览器缓存、上图 Application 清除 Storage、调用 clear 代码清除;否则会一直存在。这也就意味着关闭浏览器后再次打开,仍然可以缓存,适合持久化缓存应用场景
sessionStorage 中的数据则和会话窗口有关,多个 tab 栏中可以公用,但一旦浏览器关闭,则数据清除,适合临时存储登录 token
监听变化
当 Web Storage 发生变化时,会触发 storage 事件,回调参数中会返回变更的存储值
js
window.addEventListener('storage', (event) => {
// 来自清除缓存,变更 cookie
if (e.key == null) {
docCookies.removeItem('pageLoaded');
docCookies.removeItem('detailLoaded')
}
})
这个事件可以用来配合 css inline 进行极致的性能优化(适用于 PHP 的静态模版渲染、SSR),如果是第一次加载,则将 css 的内容放到 html 的 style 中;如果 css 缓存了,则从缓存中获取通过 link 加载 css,配合着将脚本放到 body 底部,可以做到首屏渲染无需请求任何资源
注意:这里要求 css 的内容不能太大,如果将 css 以 style 形式放到 html 中,对 Doc 文档的 fetch 影响较大,则得不偿失(一般情况下,几十 KB 的大小,对 html 的下载时间的影响都不大)
无痕模式下不可用
浏览器会在无痕模式下禁用 Web Storage,使用时需要进行可用性检测
typeof Storage !== "undefined"
大小问题
尽管 Web Storage 拥有 5M 左右的大小,但如果存储过于大量的 json 数据,依然非常容易满;而在存储接近满时,性能会非常差,很容易造成移动端卡顿
indexDB 与 localforage
使用 indexDB 可以很好的解决上述两个问题,它是一种类似数据库操作的存储结构,具有事务处理的特性,非常适合存储表格形式的数据,使用可参考 MDN 文档
由于 indexDB 的 API 非常繁琐,推荐使用封装好的 JavaScript 库,如 localforage
localforage 有一个优雅降级策略,若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage
不支持跨域
注意,Web Storage 和 indexDB 存储的内容会保存在同一个 Origin 下,一旦跨域,就无法访问
如果需要跨域访问
- 如果是自己内部站点,拥有相同二级域,可以通过 iframe + postMessage 来进行通讯
- 另一种就是通过 WebSocket 长连接
安全考虑
避免将敏感数据存储在 Storage 中(如用户手机号等),容易受到攻击
Web Worker
一句话,Web Worker 让 JavaScript 拥有了多线程处理的能力,简直是牛逼 plus
我们可以可以抽离一部分功能到 Web Worker 中,如复杂计算、处理,在结束后,通过 postMessage 并携带结果返回给主线程
使用
主页面 js
js
// 主线程中初始化Web Worker
let myWorker = new Worker('worker.js');
// 接收Worker消息事件
myWorker.addEventListener(
'message',
function (e) {
console.log('Received message ' + e.data);
},
false
);
// 发送消息给Worker
myWorker.postMessage([42, 1337]);
worker.js
js
self.addEventListener('message', function(e) {
let numbers = e.data;
let sum = numbers.reduce(function(a, b) {
return a + b;
}, 0);
self.postMessage(sum);
});
我们就完成一个运行在后台的加法计算 worker 了
优缺点
优点:Web Worker拥有独立的内存空间和线程池,即使处理出错或内存溢出,也不会阻塞主线程;同时充分利用多核进行计算任务,极大提升页面性能
缺点:不具备 DOM 操作能力,什么 window、document 统统不能操作,可以理解,因为在多线程环境下如果随意访问DOM,你操作一下,它操作一下,以谁为准呢?所以浏览器并未开放这个权限,如果需要操作 DOM,在主线程去操作
递归处理树结构
一个经典的 Web Worker 应用场景就是将递归抽离处理,比如一颗组织树列表数据,需要处理成树结构,这完全可以抽离到 Worker 中
如果在数据层次过深时,甚至可能导致内存溢出,造成页面崩溃,抽离到 Worker 中就不存在这种顾虑了,你崩任你崩,不影响咱们的主页面;当然,对于递归函数,还是建议转化为循环形式(蹦床函数)
复杂耗时的逻辑,比如递归函数,即使进行了尾递归优化,但仍然有可能耗时较长,很影响页面性能,这时就很有必要将其抽离到 Worker 中
风险
避免过度使用(好像不太需要担心,实际用的人并不多 0.0~),这也很好理解,每一个 Worker 说白了就是分配一个线程,而每一个线程是需要占据一定的内存的,过多会影响整体性能(之前在 node 多线程与单线程讨论过)
错误使用:比如一直不停的给主线程 postMessage,导致主线程被占用阻塞;当然这都是很低级的错误,也很容易发现,使用时稍加注意即可
其他待查漏补缺项
- canvas 图形绘制
- 拖拽 API
- SVG 矢量图形
- 音视频处理
- 地理定位
上述模块不是不常用,而是这些内容过于庞大,比如 canvas,甚至可以作为专项深入学习,咱目前的水平也就是照着 API 绘制绘制形状,写点轨迹动画;并没有深入使用,也就没踩过什么坑值得总结,留待将来查漏补缺吧~
结束语
作为一个油盐不进的爱卷人士,这当然不是一个结束,后续将会持续进行更新。To Be Continue...