ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[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://`),它所加载的脚本,必须来自网络。