今天
好程序员
分享
Web
前端知识之
HTML
。
Web
前端技术由
HTML
、
CSS
和
Javascript
三大部分构成,而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学习新的知识点,因此对于初学者很难理清楚整个体系的脉络结构。
1
、
BOM
BOM
是
BrowserObjectModel
的缩写,即浏览器对象模型,当一个浏览器页面初始化时,会在内存创建一个全局的对象,用以描述当前窗口的属性和状态,这个全局对象被称为浏览器对象模型,即
BOM
。
BOM
的核心对象就是
window
,
window
对象也是
BOM
的顶级对象,其中包含了浏览器的
6
个核心模块:
document-
即文档对象,渲染引擎在解析
HTML
代码时,会为每一个元素生成对应的
DOM
对象,由于元素之间有层级关系,因此整个
HTML
代码解析完以后,会生成一个由不同节点组成的树形结构,俗称
DOM
树,
document
用于描述
DOM
树的状态和属性,并提供了很多操作
DOM
的
API
。
frames-HTML
子框架,即在浏览器里嵌入另一个窗口,父框架和子框架拥有独立的作用域和上下文。
history-
以栈
(FIFO)
的形式保存着页面被访问的历史记录,页面前进即入栈,页面返回即出栈。
location-
提供了当前窗口中加载的文档相关信息以及一些导航功能。
navigator-
用来描述浏览器本身,包括浏览器的名称、版本、语言、系统平台、用户特性字符串等信息。
screen-
提供了浏览器显示屏幕的相关属性,比如显示屏幕的宽度和高度,可用宽度和高度。
2
、
DOM
系统
DOM
是
DocumentObjectModel
的缩写,即文档对象模型,是所有浏览器公共遵守的标准,
DOM
将
HTML
和
XML
文档映射成一个由不同节点组成的树型结构,俗称
DOM
树。其核心对象是
document
,用于描述
DOM
树的状态和属性,并提供对应的
DOM
操作
API
。随着历史的发展,
DOM
被划分为
1
级、
2
级、
3
级,共
3
个级别:
1
级
DOM-
在
1998
年
10
月份成为
W3C
的提议,由
DOM
核心与
DOM
HTML
两个模块组成。
DOM
核心能映射以
XML
为基础的文档结构,允许获取和操作文档的任意部分。
DOM
HTML
通过添加
HTML
专用的对象与函数对
DOM
核心进行了扩展。
2
级
DOM-
鉴于
1
级
DOM
仅以映射文档结构为目标,
DOM
2
级面向更为宽广。通过对原有
DOM
的扩展,
2
级
DOM
通过对象接口增加了对鼠标和用户界面事件
(DHTML
长期支持鼠标与用户界面事件
)
、范围、遍历
(
重复执行
DOM
文档
)
和层叠样式表
(CSS)
的支持。同时也对
DOM
1
的核心进行了扩展,从而可支持
XML
命名空间。
3
级
DOM-
通过引入统一方式载入和保存文档和文档验证方法对
DOM
进行进一步扩展,
DOM3
包含一个名为“
DOM
载入与保存”的新模块,
DOM
核心扩展后可支持
XML1.0
的所有内容,包括
XML
Infoset
、
XPath
、和
XMLBase
。
浏览器对不同级别
DOM
的支持情况如下所示:
从图中可以看出,移动端常用的
Webkit
内核浏览器目前只支持
DOM2
,而不支持
DOM3
。
3
、事件系统
事件是用户与页面交互的基础,到目前为止,
DOM
事件从
PC
端的鼠标事件
(mouse)
发展到了移动端的触摸事件
(touch)
和
手势事件
(guesture)
,
touch
事件描述了手指在屏幕操作的每一个细节,
guesture
则是描述多手指操作时更为复杂的情况,总结如下:
第一根手指放下,触发
touchstart
,除此之外什么都不会发生
手指滑动时,触发
touchmove
第二根手指放下,触发
gesturestart
触发第二根手指的
touchstart
立即触发
gesturechange
任意手指移动,持续触发
gesturechange
第二根手指弹起时,触发
gestureend
,以后将不会再触发
gesturechange
触发第二根手指的
touchend
触发
touchstart(
多根手指在屏幕上,提起一根,会刷新一次全局
touch)____
弹起第一根手指,触发
touchend
更多关于手势事件的介绍请参考:
gesture
事件处理复杂手势
DOM2.0
模型将事件处理流程分为三个阶段,即事件捕获阶段、事件处理阶段、事件冒泡阶段,如图所示:
事件捕获:当用户触发点击事件后,顶层对象
document
就会发出一个事件流,从最外层的
DOM
节点向目标元素节点传递,最终到达目标元素。
事件处理:当到达目标元素之后,执行目标元素绑定的处理函数。如果没有绑定监听函数,则不做任何处理。
事件冒泡:事件流从目标元素开始,向最外层
DOM
节点传递,途中如果有节点绑定了事件处理函数,这些函数就会被执行。
利用事件冒泡原理可以实现事件委托
,所谓事件委托,就是在父元素上添加事件监听器,用以监听和处理子元素的事件,避免重复为子元素绑定相同的事件。当目标元素的事件被触发以后,这个事件就从目标元素开始,向最外层元素传递,最终冒泡到父元素上,父元素再通过
event.target
获取到这个目标元素,这样做的好处是,父元素只需绑定一个事件监听,就可以对所有子元素的事件进行处理了,从而减少了不必要的事件绑定,对页面性能有一定的提升。
4
、
HTML
解析过程
浏览器加载
html
文件以后,渲染引擎会从上往下,一步步来解析
HTML
标签,大致过程如下:
用户输入网址,浏览器向服务器发出请求,服务器返回
html
文件
;
渲染引擎开始解析
html
标签,并将标签转化为
DOM
节点,生成
DOM
树
;
如果
head
标签中引用了外部
css
文件,则发出
css
文件请求,服务器返回该文件,该过程会阻塞后面的解析
;
如果引用了外部
js
文件,则发出
js
文件请求,服务器返回后立即执行该脚本,这个过程也会阻塞
html
的解析
;
引擎开始解析
body
里面的内容,如果标签里引用了
css
样式,就需要解析刚才下载好的
css
文件,然后用
css
来设置标签的样式属性,并生成渲染树
;
如果
body
中的
img
标签引用了图片资源,则立即向服务器发出请求,此时引擎不会等待图片下载完毕,而是继续解析后面的标签
;
服务器返回图片文件,由于图片需要占用一定的空间,会影响到后面元素的排版,因此引擎需要重新渲染这部分内容
;
如果此时
js
脚本中运行了
style.display="none"
,布局被改变,引擎也需要重新渲染这部分代码
;
直到
html
结束标签为止,页面解析完毕。
5
、重绘和回流
当渲染树中的一部分
(
或全部
)
因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流。比如上面的
img
文件加载完成后就会引起回流,每个页面至少需要一次回流,就是在页面第一次加载的时候。
当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如
background-color
。则就叫称为重绘。
从上面可以看出,回流必将引起重绘,而重绘不一定会引起回流。会引起重绘和回流的操作如下:
添加、删除元素
(
回流
+
重绘
)
隐藏元素,
display:none(
回流
+
重绘
)
,
visibility:hidden(
只重绘,不回流
)
移动元素,比如改变
top,left
的值,或者移动元素到另外一个父元素中。
(
重绘
+
回流
)
对
style
的操作
(
对不同的属性操作,影响不一样
)
还有一种是用户的操作,比如改变浏览器大小,改变浏览器的字体大小等
(
回流
+
重绘
)
另外,
transform
操作不会引起重绘和回流,是一种高效率的渲染。这是因为
transform
属于合成属性,对合成属性进行
transition/animation
动画时将会创建一个合成层,这使得动画元素在一个独立的层中进行渲染,当元素的内容没有发生改变,就没必要进行重绘,浏览器会通过重新复合来创建动画帧。
6
、本地存储
本地存储最原始的方式就是
cookie,cookie
是存放在本地浏览器的一段文本,数据以键值对的形式保存,可以设置过期时间。但是
cookie
不适合大量数据的存储,因为每请求一次页面,
cookie
都会发送给服务器,这使得
cookie
速度很慢而且效率也不高。因此
cookie
的大小被限制为
4k
左右
(
不同浏览器可能不同
,
分
HOST)
,如下所示:
Firefox
和
Safari
允许
cookie
多达
4097
个字节,包括名
(name)
、值
(value)
和等号。
Opera
允许
cookie
多达
4096
个字节,包括:名
(name)
、值
(value)
和等号。
InternetExplorer
允许
cookie
多达
4095
个字节,包括:名
(name)
、值
(value)
和等号。
在所有浏览器中,任何
cookie
大小超过限制都被忽略,且永远不会被设置。
html5
提供了两种在客户端存储数据的新方法:
localStorage
和
sessionStorage,
它们都是以
key/value
的形式来存储数据,前者是永久存储,后者的存储期限仅限于浏览器会话
(session)
,即当浏览器窗口关闭后,
sessionStorage
中的数据被清除。
localStorage
的存储空间大约
5M
左右
(
不同浏览器可能不同,分
HOST)
,这个相当于一个
5M
大小的前端数据库,相比于
cookie
,可以节约带宽,但
localStorage
在浏览器隐私模式下是不可读取的,当存储数据超过了
localStorage
的存储空间后会抛出异常。
此外,
H5
还提供了逆天的
Websql
和
indexedDB
,允许前端以关系型数据库的方式来存储本地数据,相对来说,这个功能目前应用的场景比较少,此处不作介绍。
7
、浏览器缓存机制
浏览器缓存机制是指通过
HTTP
协议头里的
Cache-Control(
或
Expires)
和
Last-Modified(
或
Etag)
等字段来控制文件缓存的机制。
Cache-Control
用于控制文件在本地缓存有效时长。最常见的,比如服务器回包:
Cache-Control:max-age=600
表示文件在本地应该缓存,且有效时长是
600
秒
(
从发出请求算起
)
。在接下来
600
秒内,如果有请求这个资源,浏览器不会发出
HTTP
请求,而是直接使用本地缓存的文件。
Last-Modified
是标识文件在服务器上的最新更新时间。下次请求时,如果文件缓存过期,浏览器通过
If-Modified-Since
字段带上这个时间,发送给服务器,由服务器比较时间戳来判断文件是否有修改。如果没有修改,服务器返回
304
告诉浏览器继续使用缓存
;
如果有修改,则返回
200
,同时返回最新的文件。
Cache-Control
通常与
Last-Modified
一起使用。一个用于控制缓存有效时间,一个在缓存失效后,向服务查询是否有更新。
Cache-Control
还有一个同功能的字段:
Expires
。
Expires
的值一个绝对的时间点,如:
Expires:Thu,10Nov
201508:45:11GMT
,表示在这个时间点之前,缓存都是有效的。
Expires
是
HTTP1.0
标准中的字段,
Cache-Control
是
HTTP1.1
标准中新加的字段,功能一样,都是控制缓存的有效时间。当这两个字段同时出现时,
Cache-Control
是高优化级的。
Etag
也是和
Last-Modified
一样,对文件进行标识的字段。不同的是,
Etag
的取值是一个对文件进行标识的特征字串。在向服务器查询文件是否有更新时,浏览器通过
If-None-Match
字段把特征字串发送给服务器,由服务器和文件最新特征字串进行匹配,来判断文件是否有更新。没有更新回包
304
,有更新回包
200
。
Etag
和
Last-Modified
可根据需求使用一个或两个同时使用。两个同时使用时,只要满足基中一个条件,就认为文件没有更新。
另外有两种特殊的情况:
手动刷新页面
(F5)
,浏览器会直接认为缓存已经过期
(
可能缓存还没有过期
)
,在请求中加上字段:
Cache-Control:max-age=0
,发包向服务器查询是否有文件是否有更新。
强制刷新页面
(Ctrl+F5)
,浏览器会直接忽略本地的缓存
(
有缓存也会认为本地没有缓存
)
,在请求中加上字段:
Cache-Control:no-cache
(
或
Pragma:no-cache)
,发包向服务重新拉取文件。
8
、
History
用户访问网页的历史记录通常会被保存在一个类似于栈的对象中,即
history
对象,点击返回就出栈,跳下一页就入栈。它提供了以下方法来操作页面的前进和后退:
window.history.back()
返回到上一个页面
window.history.forward()
进入到下一个页面
window.history.go([delta])
跳转到指定页面
HTML5
对
HistoryApi
进行了增强,新增了两个
Api
和一个事件,分别是
pushState
、
replaceState
和
onpopstate
:
pushState
是往
history
对象里添加一个新的历史记录,即压栈。
replaceState
是替换
history
对象中的当前历史记录。
当点击浏览器后退按钮或
js
调用
history.back
都会触发
onpopstate
事件。
与其类似的还有一个事件:
onhashchange
,
onhashchange
是老
API
,浏览器支持度高,本来是用来监听
hash
变化的,但可以被利用来做客户端前进和后退事件的监听,而
onpopstate
是专门用来监听浏览器前进后退的,不仅可以支持
hash
,非
hash
的同源
url
也支持。
9
、
HTML5
离线缓存
HTML5
离线缓存又叫
Application
Cache
,是从浏览器的缓存中分出来的一块缓存区,如果要在这个缓存中保存数据,可以使用一个描述文件
(manifestfile)
,列出要下载和缓存的资源。
manifest
文件是简单的文本文件,它告知浏览器被缓存的内容
(
以及不缓存的内容
)
。
manifest
文件可分为三个部分:
-CACHEMANIFEST-
在此标题下列出的文件将在首次下载后进行缓存
-NETWORK-
在此标题下列出的文件需要与服务器的连接,且不会被缓存
-FALLBACK-
在此标题下列出的文件规定当页面无法访问时的回退页面
(
比如
404
页面
)
离线缓存为应用带来三个优势:
离线浏览
-
用户可在应用离线时使用它们
速度
-
已缓存资源加载得更快
减少服务器负载
-
浏览器将只从服务器下载更新过或更改过的资源。
10
、
Web
语义化和
SEO
Web
语义化是指使用语义恰当的标签,使页面有良好的结构,页面元素有含义,能够让人和搜索引擎都容易理解。
SEO
是指在了解搜索引擎自然排名机制的基础之上,对网站进行内部及外部的调整优化,改进网站在搜索引擎中关键词的自然排名,获得更多的展现量,吸引更多目标客户点击访问网站,从而达到互联网营销及品牌建设的目标。
搜索引擎通过爬虫技术获取的页面就是由一堆
html
标签组成的代码,人可以通过可视化的方式来判断页面上哪些内容是重点,而机器做不到。
但搜索引擎会根据标签的含义来判断内容的权重,因此,在合适的位置使用恰当的标签,使整个页面的语义明确,结构清晰,搜索引擎才能正确识别页面中的重要内容,并予以较高的权值。比如
h2~h7
这几个标签在
SEO
中的权值非常高,用它们作页面的标题就是一个简单的
SEO
优化。