[TOC]
>[info] 这里不讨论浏览器兼容性
# 语义化
语义化标签:`<header>, <nav>, <main>, <article>, <aside>, <footer>`以及`<address>, <mark>, <time>`等
语义化的优点:
* 易于用户阅读,样式丢失的时候能让页面呈现清晰的结构。
* 有利于 SEO,搜索引擎根据标签来确定上下文和各个关键字的权重。
* 方便其他设备解析,如盲人阅读器根据语义渲染网页
* 有利于开发和维护,语义化更具可读性,代码更好维护,与 CSS3 关系更和谐。
关于 SEO 优化的可以使用 title 和 meta,比如
``` html
<html>
<head>
<title>标题内容</title>
<meta name="description" content="描述内容">
<meta name="keyword" content="关键字1,关键字2,—">
</head>
</html>
```
# 表单增强
## input type 属性扩充
* search: 呈现一个搜索框
* tel: 输入电话号码,可以采用 pattern 和 maxlength 来限定输入的格式,比如
```html
<input type="tel" name="tel" value="" placeholder="请输入手机号" pattern="1[3-8][0-9]{9}" title="请输入11位手机号">
```
提交表单时,浏览器会校验输入结果。如果校验失败,会给出提示信息
* url: 输入 URL 地址
* email: 输入电子邮件地址
* data: 输入日期
* color: 输入颜色, 会调出选色板
* range: 滑块输入
## input 通过属性进行表单验证
* required: 标记当前 Input 元素为必填
```html
<input type="text" placeholder="此项必填" required>
```
* pattern: 采用正则表达式验证表单输入
关于去除`<input type="file">`显示的"未选择任何文字"的默认提示的问题,比如下面这样
![](https://box.kancloud.cn/e3f0562aaa089d147831a83b5bb025cf_690x242.png =400x)
这里提供一种思路: `<label>`标签的 for 属性可以触发对应的表单控件,把 input 的样式隐藏掉(比如 opacity: 0)用一个 button 来代替即可
``` html
<label for="sendImage" class="imageLable">
<input type="button" value="image" />
<input id="sendImage" type="file" value="image"/> <!--定义类型为 file 即可让用户选择文件-->
</label>
```
# canvas 与 SVG
canvas 与 svg: canvas 通过 JavaScript 来绘制 2D 图形,是逐像素进行渲染的;svg(Scalable Vector Graphics)基于 XML,具有可缩放的矢量图形特性,这意味着在对 SVG 图形做任何尺寸变化时不会出现模糊和失真。
具体比较如下,来源:w3school
- Canvas
- 依赖分辨率
- 不支持事件处理器
- 弱的文本渲染能力
- 能够以 .png 或 .jpg 格式保存结果图像
- 最适合图像密集型的游戏,其中的许多对象会被频繁重绘
- Canvas 是逐像素进行渲染的。
在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。
- SVG
- 不依赖分辨率
- 支持事件处理器
- 最适合带有大型渲染区域的应用程序(比如谷歌地图)
- 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
- 不适合游戏应用
canvas 相关的文档正在写作中:[https://www.kancloud.cn/chenmk/canvas/1315494](https://www.kancloud.cn/chenmk/canvas/1315494)
# 多媒体相关 API
\<video> 用于加载视频文件:
```html
<video width="320" height="240" controls="controls">
<source src="movie.ogg" type="video/ogg">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
```
- Ogg 文件适用于 Firefox、Opera 以及 Chrome 浏览器。要确保适用于 Safari 浏览器,视频文件必须是 MPEG4 类型。
- video 元素允许多个 source 元素。source 元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式。
- controls 属性供添加播放、暂停和音量控件。
相关链接:[https://www.w3school.com.cn/html5/html\_5\_video.asp](https://www.w3school.com.cn/html5/html_5_video.asp)
\<audio> 用于加载音频文件:
```html
<audio controls="controls">
<source src="song.ogg" type="audio/ogg">
<source src="song.mp3" type="audio/mpeg">
Your browser does not support the audio tag.
</audio>
```
[这篇文章](https://www.jianshu.com/p/1fe701c9179f) 记录了其相关 API
一般我们都会取消掉浏览器提供的默认控件,使用相应的 API 来做自己的视频、音频播放器,以后有空做个玩玩...
# history API
| 属性 | 描述 |
| --- | --- |
| state -> window.history.state | 返回一个表示历史堆栈顶部的状态的值 |
| length -> window.history.length | 返回一个整数,表示会话历史中的元素数目
| 方法 | 描述 |
| --- | --- |
| back() | 返回上一页 |
| forward() | 在浏览器历史记录中前往下一页 |
| go() | 参数为 -1 时前往上一页,参数为 1 时前往下一页 |
| pushState(stateObject, title, URL) | 按指定的名称和 URL(如果提供该参数)将数据 push 进会话历史栈,数据被 DOM 进行不透明处理;你可以指定任何可以被序列化的 javaScript 对象 |
| replaceState(stateObject, title, URL) | 按指定的数据、名称和 URL(如果提供该参数)更新历史栈上最新的入口。这个数据被 DOM 进行了不透明处理。你可以指定任何可以被序列化的 JavaScript 对象 |
| 事件 | 描述 |
| --- | --- |
| popState | 浏览器跳转到新的状态时会触发 popState 事件,该事件将携带这个 stateObject 参数的副本 |
```js
function nextPage () {
// doSomething...
window.history.pushState({ page: pageIndex }, null, window.location.href)
}
// 用户单击返回或前进按钮时触发
window.addEventListener('popstate', function (event) {
let page = event.state.page // 从 event 对象中获取这个“页面”存储的状态
})
```
# 文件 API
总之先看一段代码,这是写聊天室时从本地选择图片的部分代码,用户点击`<input type="file">`时触发。
```javaScript
// 选择图片时触发
chooseImage(e) {
// 检查是否有文件被选中
let _this = this
let file = e.target.files[0] // 获取到被选中的图片的路径
let reader = new FileReader()
if (file && file.type.match('image.*')) {
reader.readAsDataURL(file)
} else {
// not image
}
// 注意是异步读取
reader.onloadend = function(e) {
// do something after read image
// console.log(reader.result) // blob 类型
let imageData = reader.result
_this.historyMessages.push({
username: _this.username,
time: new Date().toTimeString().substr(0, 8),
content: `<img src="${imageData}" style="width:100%">`, // 本来想把style写在css里的发现无法选择到img
ifImage: true
})
_this.$socket.emit('postImg', imageData)
}
}
```
要理解这段代码,首先要明确 e.target.files 这个数组中的 File 对象的格式,然后要知道FileReader 类型提供了哪些方法。
HTML5 在DOM 中为文件输入元素添加了一个 files 集合。在通过文件输入字段选择了一或多个文件时,files 集合中将包含一组 File 对象,每个 File 对象对应着一个文件。每个 File 对象都有下列只读属性。
- name:本地文件系统中的文件名。
- size:文件的字节大小。
- type:字符串,文件的 MIME 类型。
- lastModifiedDate:字符串,文件上一次被修改的时间
FileReader 类型实现的是一种异步文件读取机制。可以把 FileReader 想象成 XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器。为了读取文件中的数据,FileReader 提供了如下几个方法。
- readAsText(file,encoding):以纯文本形式读取文件,将读取到的文本保存在 result 属性中。第二个参数用于指定编码类型,是可选的。
- readAsDataURL(file):读取文件并将文件以数据 URI 的形式保存在 result 属性中。
- readAsBinaryString(file):读取文件并将一个字符串保存在 result 属性中,字符串中的每个字符表示一字节。
- readAsArrayBuffer(file):读取文件并将一个包含文件内容的 ArrayBuffer 保存在
result 属性中。
`URL:Uniform/Universal Resource Locator` ,统一资源定位符
`URI:Uniform Resource Identifier` ,统一资源标识符(代表一种标准)
>关系:URI 属于 URL 更高层次的抽象,一种字符串文本标准。就是说,URI 属于父类,而 URL 属于 URI 的子类。URL 是 URI 的一个子集。二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。
由于读取过程是异步的,因此 FileReader 也提供了几个事件。常用的事件有
- progress 是否又读取了新数据
- error 是否发生了错误
- end 是否已经读完了整个文件
- load 文件加载成功后触发
- loadend 该事件发生就意味着已经读取完整个文件,或者读取时发生了错误,或者读取过程被中断。
# 其他 API
## 地理位置
地理位置 API 能够访问到用户的当前位置信息,访问前必须得到用户的明确许可。
在浏览器中的实现是 navigator.geolocation 对象,这个对象包含 3 个方法
getCurrentPosition(cb1, cb2(option), obj(option)): 调用该方法会触发请求用户共享地理位置信息的对话框,接收3个参数:成功的回调、可选的失败的回调函数和可选的选项对象
成功回调函数会接收到一个 Position 对象参数,该对象有两个属性:coords 和 timestamp
coords对象包含以下与位置相关的信息:
- latitude:以十进制度数表示的纬度。
- longitude:以十进制度数表示的经度。
- accuracy:经、纬度坐标的精度,以米为单位。
有些浏览器还可能会在 coords 对象中提供如下属性。
- altitude:以米为单位的海拔高度,如果没有相关数据则值为 null。
- altitudeAccuracy:海拔高度的精度,以米为单位,数值越大越不精确。
- heading:指南针的方向,0°表示正北,值为 NaN 表示没有检测到数据。
- speed:速度,即每秒移动多少米,如果没有相关数据则值为 null。
在实际开发中,latitude 和 longitude 是大多数 Web 应用最常用到的属性。例如,以下代码将在地图上绘制用户的位置:
``` js
navigator.geolocation.getCurrentPosition(function (position) {
drawMapCenteredAt(position.coords.latitude, position.coords.longitude)
})
```
完整的示例:
``` js
navigator.geolocation.getCurrentPosition(function (position) { // 成功的回调
drawMapCenteredAt(position.coords.latitude, position.coords.longitude)
}, function (error) { // 失败的回调
console.log(`Error code: ${error.code}`) // 错误类型:1 用户拒绝共享 2 位置无效 3 超时
console.log(`Error message ${error.message}`)
}, { // 选项对象
enableHighAccuracy: true, // 表示必须尽可能使用最准确的位置信息
timeout: 5000, // 表示等待位置信息的最长时间
maximumAge: 25000 // 表示上一次取得的坐标信息的有效时间,ms 为单位,如果超时则重新获取
})
```
如果要跟踪用户的位置,可以使用 **watchPosition** 方法
## 跨文档消息传递
即来自不同域的页面间传递消息,其核心是 postMessage() 方法,postMessage() 方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。
``` js
// 注意:所有支持 XDM 的浏览器也支持 iframe 的 contentWindow 属性
var iframeWindow = document.getElementById('myframe').contentWindow
iframeWindow.postMessage('A secret', 'http://www.wrox.com')
```
接收到 XDM 消息时,会触发 window 对象的 message 事件。这个事件是以异步形式触发的,因此从发送消息到接收消息(触发接收窗口的 message 事件)可能要经过一段时间的延迟。触发 message 事件后,传递给 onmessage 处理程序的事件对象包含以下三方面的重要信息。
- data:作为 postMessage() 第一个参数传入的字符串数据。
- origin:发送消息的文档所在的域,例如`"http://www.wrox.com"`。
- source:发送消息的文档的 window 对象的代理。这个代理对象主要用于在发送上一条消息的
窗口中调用 postMessage() 方法。如果发送消息的窗口来自同一个域,那这个对象就是 window。
通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
``` js
// 发送消息端
window.parent.postMessage('message', 'http://test.com')
// 接收消息端
var mc = new MessageChannel()
mc.addEventListener('message', event => {
var origin = event.origin || event.originalEvent.origin
if (origin === 'http://test.com') {
console.log('验证通过')
}
})
```
更多信息参考<a href="https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel" target="_blank"> MDN</a>
## Web Worker
参考链接:[http://www.ruanyifeng.com/blog/2018/07/web-worker.html](http://www.ruanyifeng.com/blog/2018/07/web-worker.html)
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点。
(1)**同源限制**
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(2)**DOM 限制**
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用`document`、`window`、`parent`这些对象。但是,Worker 线程可以访问`navigator`对象和`location`对象。
(3)**通信联系**
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
(4)**脚本限制**
Worker 线程不能执行`alert()`方法和`confirm()`方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
(5)**文件限制**
Worker 线程无法读取本地文件,即不能打开本机的文件系统(`file://`),它所加载的脚本,必须来自网络。
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直线、矩形、多边形
- Part2-曲线图形
- Part3-线条操作
- Part4-文本操作
- Part5-图像操作
- Part6-变形操作
- Part7-像素操作
- Part8-渐变与阴影
- Part9-路径与状态
- Part10-物理动画
- Part11-边界检测
- Part12-碰撞检测
- Part13-用户交互
- Part14-高级动画
- CSS
- SCSS
- codePen
- 速查表
- 面试题
- 《CSS Secrets》
- SVG
- 移动端适配
- 滤镜(filter)的使用
- JS
- 基础概念
- 作用域、作用域链、闭包
- this
- 原型与继承
- 数组、字符串、Map、Set方法整理
- 垃圾回收机制
- DOM
- BOM
- 事件循环
- 严格模式
- 正则表达式
- ES6部分
- 设计模式
- AJAX
- 模块化
- 读冴羽博客笔记
- 第一部分总结-深入JS系列
- 第二部分总结-专题系列
- 第三部分总结-ES6系列
- 网络请求中的数据类型
- 事件
- 表单
- 函数式编程
- Tips
- JS-Coding
- Framework
- Vue
- 书写规范
- 基础
- vue-router & vuex
- 深入浅出 Vue
- 响应式原理及其他
- new Vue 发生了什么
- 组件化
- 编译流程
- Vue Router
- Vuex
- 前端路由的简单实现
- React
- 基础
- 书写规范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 与 Hook
- 《深入浅出React和Redux》笔记
- 前半部分
- 后半部分
- react-transition-group
- Vue 与 React 的对比
- 工程化与架构
- Hybird
- React Native
- 新手上路
- 内置组件
- 常用插件
- 问题记录
- Echarts
- 基础
- Electron
- 序言
- 配置 Electron 开发环境 & 基础概念
- React + TypeScript 仿 Antd
- TypeScript 基础
- 样式设计
- 组件测试
- 图标解决方案
- Algorithm
- 排序算法及常见问题
- 剑指 offer
- 动态规划
- DataStruct
- 概述
- 树
- 链表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 课程实战记录
- 服务器
- 操作系统基础知识
- Linux
- Nginx
- redis
- node.js
- 基础及原生模块
- express框架
- node.js操作数据库
- 《深入浅出 node.js》笔记
- 前半部分
- 后半部分
- 数据库
- SQL
- 面试题收集
- 智力题
- 面试题精选1
- 面试题精选2
- 问答篇
- Other
- markdown 书写
- Git
- LaTex 常用命令