精进之HTML5篇
HTML、XML、XHTML、SGML的关系
-
GML: 是第一代置标语言,使文档能明确将标示和内容分开。 GML主要用来解决不同系统中文档格式不同的问题。
-
SGML(标准通用标记语言)是一个标准,告诉我们怎么去指定文档标记。在 GML 的基础上进行整理,形成了一套非常严谨的文件描述方法。它的组成包括语法定义,DTD(W3C DTD 教程),文件实例三部分。
-
HTML (HyperText Markup Language) / 超文本标记语言: 是人们抽取了 SGML的一个微小子集而提取出来的。其早期规范比较松散,但比较易学。经过一系列修订,到现在说的 HTML 一般指 HTML 4.01;
-
XML (Extensible Markup Language )/ 可扩展标记语言: 也是 SGML 的一个子集,但使用比较严格的模式。
-
XHTML (Extensible Hypertext Markup Language) / 可扩展超文本标记语: 它的出现是因为HTML扩充性不好,内容的表现跟不上时代的变化(如无法表示某些化学符号等),以及因为性能的问题,官方逐渐趋于严格的模式,所以使用 XML的严格规则的XHTML成了W3C 计划中 HTML 的替代者。
总之,SGML是所有类型的父类,较旧的HTML利用SGML,HTML4.0使用派生自XML的XHTML
HTML5简介
- HTML5是HTML最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定。
- HTML5的设计目的是为了在移动设备上支持多媒体。
- HTML5简单易学。
什么是HTML5
- HTML5 是下一代 HTML 标准。
- HTML5本身并非技术,而是标准。它所使用的技术早已很成熟,国内通常所说的html5实际上是html与css3及JavaScript和api等的一个组合,大概可以用以下公式说明:HTML5≈HTML+CSS3+JavaScript+API
- HTML , HTML 4.01的上一个版本诞生于 1999 年。自从那以后,Web 世界已经经历了巨变。
- HTML5 仍处于完善之中。然而,大部分现代浏览器已经具备了某些 HTML5 支持。
- HTML5 受包括Firefox(火狐浏览器),IE9及其更高版本,Chrome(谷歌浏览器),Safari,Opera等国外主流浏览器的支持;国内的傲游浏览器(Maxthon), 360浏览器、搜狗浏览器、QQ浏览器、猎豹浏览器等同样具备支持HTML5的能力。
HTML5如何起步的
- HTML5 是 W3C 与 WHATWG 合作的结果,WHATWG 指 Web Hypertext Application Technology Working Group。
- WHATWG 致力于 web 表单和应用程序,而 W3C 专注于 XHTML 2.0。在 2006 年,双方决定进行合作,来创建一个新版本的 HTML。
- HTML5 中的一些有趣的新特性:
-
用于绘画的 canvas 元素
-
用于媒介回放的 video 和 audio 元素
-
对本地离线存储的更好的支持
-
新的特殊内容元素,比如 article、footer、header、nav、section
-
新的表单控件,比如 calendar、date、time、email、url、search
HTML5 < !DOCTYPE>
1、DOCTYPE的作用:
声明文档的解析类型(document.compatMode)、避免浏览器使用怪异模式。
- document.compatMode:BackCompat:怪异模式,浏览器使用自己的怪异模式解析渲染页面、(默认)。
- document.compatMode: CSS1Compat:标准模式、浏览器使用W3C标准解析渲染页面。
这个属性会被浏览器识别并使用,但是如果你的页面没有DOCTYPE的声明,那么compatMode默认就是BackCompat。浏览器按照自己的方式解析渲染页面,那么,在不同的浏览器就会显示不同的样式、很可能出现兼容问题。
如果你的页面添加了那么,那么就等同于开启了标准模式,那么浏览器就得老老实实的按照W3C的标准解析渲染页面,这样一来,你的页面在所有的浏览器里显示的就都是一个样子了。这就是< !DOCTYPE html>的作用
2、HTML5 为什么只需要写 < !DOCTYPE HTML>?
-
HTML5不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为
-
而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型
-
如今的HTML5标准制定了两种实现语法HTML和XHTML。HTML不再基于任何特定的标记语言系统,它有自己完整的标准。而XHTML是XML的一个应用。
HTML5新特性
- 用于绘画的 canvas 元素
- 用于媒介回放的 video 和 audio 元素
- 对本地离线存储的更好的支持loacalStorage、sessionStorage
- 新的特殊内容元素,比如 article、footer、header、nav、section
- 新的表单控件,比如 calendar、date、time、email、url、search
HTML5web储存
使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本。
什么是应用程序缓存(Application Cache)?
HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。
应用程序缓存为应用带来三个优势:
- 离线浏览 - 用户可在应用离线时使用它们
- 速度 - 已缓存资源加载得更快
- 减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。
我用一段话来赘述下为什么要使用Application Cache技术:
当页面有些元素它们是不变的,你可以使用Application Cache技术离线缓存掉,每次访问这些缓存掉的元素就不需要再请求服务器了,当有些东西经常变,那就让它们每次请求服务器吧!
开始使用Application Cache
涉及角色:服务器和html文件
服务器端需要做的事情
管理维护manifest.appcache文件,检查manifest清单中是否有无法访问的文件,并及时更新,以免造成损失。
manifest文件(W3C建议文件扩展名为.appcache)
manifest 文件是简单的文本文件,它告知浏览器被缓存的内容(以及不缓存的内容)。
manifest 文件可分为三个部分:
- CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
- NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
- FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)
一、CACHE MANIFEST(它是必须的)
CACHE MANIFEST
/reset.css
/logo.gif
/hx.js
manifest 文件列出了三个资源:一个 CSS 文件,一个 GIF 图像,以及一个 JavaScript 文件。当 manifest 文件加载后,浏览器会从网站的根目录下载这三个文件。然后,无论用户何时与因特网断开连接,这些资源依然是可用的。
注意:文件位置根据文件在服务器的实际目录,确保路径正确。
总结:CACHE MANIFEST列出的资源是需要在本地缓存的文件(要缓存的文件)
二、NETWORK
NETWORK:
nav.html
NETWORK 小节规定文件 “nav.html” 永远不会被缓存,且离线时不可用。
NETWORK:
*
也可以使用星号“ * ”来指示所有其他资源/文件都需要因特网连接。
注意:千万不要把首页index放入NETWORK中禁止缓存,否则插件等无法使用。
总结:NETWORK列出的资源是需要每次请求的动态资源文件(不缓存的文件)
三、FALLBACK
FALLBACK:
/index/ /404.html
FALLBACK 小节规定如果无法建立因特网连接,则用 “404.html” 替代 /index/ 目录中的所有文件。
注意:第一个 URI 是资源,第二个是替补。
总结:FALLBACK列出的资源是如果某个文件无法联网或接入失败,则使用后一个替补显示。(友好的替补页面)
完整的manifest文件
CACHE MANIFEST
# Files that need to be cached2014.6.5
/reset.css
/logo.gif
/hx.js
NETWORK:
#Files that do not need caching2014.6.5
nav.html
FALLBACK:
#Files to be replaced2014.6.5
/index/ /404.html
注意:#代表注释行,看似简单的注释行却有着很大的用处,为什么这么说呢,因为应用的缓存会在其 manifest 文件更改时被更新。如果您编辑了一幅图片,或者修改了一个 JavaScript 函数,这些改变都不会被重新缓存。更新注释行中的日期和版本号、时间戮或md5码等,是一种使浏览器重新缓存文件的办法。
html需要做的事情
只需要引入manifest.appcache文件
<!DOCTYPE HTML>
<html manifest="manifest.appcache">
Application Cache生命销毁规则
- (1)用户清空浏览器的缓存,此时Application Cache本地缓存将销毁。
- (2)manifest文件被修改时,因为应用的缓存会在其 manifest 文件更改时被更新。如果您编辑了一幅图片,或者修改了一个 JavaScript 函数,这些改变都不会被重新缓存,此时Application Cache本地缓存将销毁。
- (3)由程序来更新应用缓存
深入manifest.appcache文件
首先提醒的就是,千万不要把index首页禁止缓存,虽然放入NETWORK也不起作用,这是一种规范,也是一种规则,请遵守。
HTTP相关的缓存头域以及https的缓存页面限制,将被manifest所无视,所以在用户代理更新页面之前,它是不会过期的,也就是说,即使是HTTPS,也可以脱机工作。
各大浏览器对应用缓存的容量限制有所不同,几乎为5MB。
当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
缓存包含manifest清单的页面,所以实际上,即使我们不显示的把包含manifest的页面,列在manifest缓存清单中,这个页面也会被缓存。
每次网站更新,服务器端要进行manifest.appcache文件的检查和更新,避免造成损失。
站点中的其他页面即使没有设置manifest属性,请求的资源如果在缓存中也从缓存中访问。
如果manifest文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。
其实,不必明确的列出Application Cache链接到的页面,默认情况下,任何包含html元素manifest属性的页面都会缓存,这些自动缓存的页面称为主条目,而清单中列出的文件称为详细条目,如果某些文件需要在线访问,可以创建 “ 白名单 ”。像在NETWORK下的条目,这些文件通常称之为网络条目,每次联网,每次都要请求服务器。
第一行CACHE MANIFEST是固定的格式,且必须要写在第一行,也必须要有,NETWORK和FALLBACK为可选项。
FALLBACK中的资源必须和manifest文件同源。
引用manifest的html必须与manifest文件同源,在同一个域下。
当manifest文件发生改变时,资源请求本身也会触发更新
注释不仅仅起到不执行的作用,上述已经详细解释了,可以是版本号,时间戳或者md5码等等。
manifest文件中的cache部分不能使用通配符,必须手动指定,没有自动化工具
在开发过程中,通过ajax与WCF进行数据交互时,常常头一次或头几次数据加载成功,以后均加载失败。
因为启用的web离线缓存机制,所以每次ajax加载数据时是从本地缓存文件中读取的,用的是ajax的get模式,因为get模式缓存(ie浏览器会,谷歌火狐不会),所以不会重新向服务器请求数据,导致数据加载失败。
改成ajax post方式后,数据 never cache,所以每次刷新网站,均会向service请求数据。
报错: Application Cache Error event: Manifest fetch failed (404)
解决方法:
- manifest 文件需要配置正确的 MIME-type,即 “text/cache-manifest”。
- manifest 的 contentType = text/cache-manifest,扩展名建议为 .appcache
- 且必须在 web 服务器上进行配置,不同的服务器配置方法不一样。
页面离线,ajax更新。
首先,你可以修改下 manifest 文件来更新这个页面,但是作为文章内容页面离线以后,就会存储在本地了,如果你是一篇章的话,那么这个文章的内容页就被存下来了,你如果以相同的 url 去访问,不管你文章里面的数据更新没有,这个离线下来的页面都不会更新了 ( 除非你更新manifest 文件 ) 。所以,你所有的动态数据,都得用 ajax 方式去获取,就像客户端一样,离线的页面应该是一个没有数据的空壳,然后通过 ajax 去拉去数据填补这个空壳。然后要注意的是,ajax 的请求地址,要写到manifest 的 network 中。
离线页面的更新(长尾问题) 网站更新了,如何更新用户本地的离线页面呢?
与很多文章中说的一样,先上线你的文件,然后修改一下页面中引入的cache.manifest文件即可,比如修改下注释,修改后,如果再访问页面,就会先去校验manifest 时候有更新,如有更新,再次刷新页面的时候,页面就会更新了。
长尾问题(非常重要):
就像前面说到的一样,如果你的 manifest 文件更新了,你访问页面,需要刷新一次,更新的页面才能 load加载进来,那么这样就有一个问题,如果你的后端数据,就是给 js ajax 接口的数据变化了,你对应的 js 也修改了。那么你修改 manifest 上线的时候,第一次开页面,页面就会出 bug 了。再刷一次页面,就好了。那么,这个第一次访问的 bug ,是我们不想看到的。
而且你不能知道用户什么时候第二次再来访问你的页面,所以你的页面一旦使用 manifest 离线,就像客户端一样,这样就出现了长尾问题。还好, manifest 有一些 js 接口,可以来判断, load 更新文件。
cache.status属性返回当前离线应用状态
UNCACHED ( 数值 0) :未启用离线应用
IDLE ( 数值 1) :已开启离线应用,但本地缓存的资源是最新的,并且未标记为废弃资源
CHECKING ( 数值 2) :当前更新缓存的状态为 “ 检查中 ”
DOWNLOADING ( 数值 3) :当前更新缓存的状态为 “ 下载资源中 ”
UPDATEREADY ( 数值 4) :当前更新缓存的状态为 “ 更新完毕 ”
OBSOLETE ( 数值 5) :已开启离线应用,但缓存资源都已标记为废弃
如果文件超出缓存5M的大小,会造成什么。
比如我A频道维护了自己的Application Cache,B频道也维护了自己的,这个时候A频道如果使用达到了一个峰值,会导致B频道所有的缓存失效。
所以,建议Application Cache存储公共资源,不要存储业务资源!
由更新机制来说,首次更新manifest时,因为页面加载已经开始甚至已经完成,缓存更新尚未完成,浏览器仍然会使用过期的资源;浏览器是当Application Cache有更新时,该次不会使用新资源,第二次才会使用。这个时候update事件中执行window.reload事件。
window.applicationCache.addEventListener("updateready", function(){
window.location.reload()
});
由上例可以知道,缓存的不只是显示定义的文件,比如上例中的applicationcache/时便会默认保存index.html为映射的数据,并且包含demo.appcache文件,很多时候会遇到一次文件更新线上老是不更新,这个时候随便在manifest配置文件中做一点修改即可更新。
做一下代码更改:
<html manifest="A.appcache">
=>
<html manifest="B.appcache">
这个时候如果不做A.appcache的更新的话,缓存将不会更新,原因是index.html被缓存了,检测的仍然是原manifest清单
各个页面统一管理自己的manifest清单,意思是a页面配置了common.js,b页面也配置了common.js,意思是a页面更新后,
b页面的manifest不更改的话,b页面依旧读取的是老版本的文件,这个有一定道理却也有一定浪费,需要公共页面做处理。
参考于
blog.csdn.net/weixin_4419…
HTML5 Web Workers
web worker 是运行在后台的 JavaScript,不会影响页面的性能。
一、什么是 Web Worker?
当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。
二、限制
- Web Worker无法访问DOM节点;
- Web Worker无法访问全局变量或是全局函数;
- Web Worker无法调用alert()或者confirm之类的函数;
- Web Worker无法访问window、document之类的浏览器全局变量;
三、worker与sharedWorker
- Web workers可分为两种类型:专用线程、共享线程。
- 专用线程随当前页面的关闭而结束;这意味着专用线程只能被创建它的页面访问。
- 与之相对应的共享线程r可以被多个页面访问。
专用线程
let worker = new Worker("worker.js");
共享线程
let worker = new SharedWorker("sharedworker.js");
四、worker的通信
专用线程
使用 onmessage() , postmessage()通信
/** 主线程 **/
let worker = new Worker ('worker.js')
worker.onmessage = (e) => {
console.log(e.data) // I post a message to main thread
}
worker.postMessage('main thread got a message')
/** 子线程 worker.js **/
onmessage = (e) => {
console.log(e.data) // main thread got a message
}
postMessage('I post a message to main thread')
共享线程
SharedWorker需要用到port属性,接收需要先connect
/** 主线程 **/
worker.port.onmessage = function(e){}
worker.port.postMessage('data');
/** 子线程 **/
addEventListener('connect', function(event){
var port = event.ports[0]
//接收
port.onmessage = function(event){
console.log(event.data);
};
//发送
port.postMessage("data");
port.start();
});
五、worker.js里引入外部js
// 引入一个脚本
importScripts('xxx.js');
// 引入多个脚本
importScripts('aaa.js', 'bbb.js', 'ccc.js');
4
六、结束线程
// 在主线程中终止
worker.terminate()
// 在子线程中终止自身
self.close()
七、错误监听
worker.addEventListener("error", function(evt){
alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename);
}, false);
worker.postMessage(10000);
});
八、使用inline的worker.js
let blob = new Blob(['/*worker.js的代码*/']);
let blobURL = window.URL.createObjectURL(blob);
worker = new Worker(blobURL);