缓存
关于缓存的好处与优点就不说了, 简单说说浏览器的缓存机制.
当浏览器向服务器发起请求时, 首先会判断是否有缓存, 如果没有缓存, 则正常向服务器发起请求;
如果有缓存, 先判断缓存是否过期, 如果未过期, 直接使用缓存;
如果过期, 则向服务器发起请求, 判断资源是否有更新, 如果有更新, 则返回新的资源(200);
如果资源未更新, 则继续使用缓存(304).
http 报文中与缓存相关的首部字段
Cache-Control
Cache-Control 可以控制告诉客户端或是服务器如何处理缓存. 只有很多, 常用的有 no-store,no-cache,max-age.
no-store 表示禁用缓存; no-cache 表示可以使用缓存, 但是每次都必须到服务器验证资源的有效性(无论资源有没有过期);max-age 表示缓存的时长, 是相对时间, 单位为秒. 优先级高于 Expires
If-None-Match 与 ETag
ETag 是资源的唯一标识, 优先级高于 Last-Modified.
If-None-Match 的值为上次请求资源文件时响应头字段 ETag 的值, 在第二次请求时作为请求头发给服务器, 服务端通过 If-None-Match 字段来判断在这两次访问期间资源有没有被修改过. 如果有修改正常返回资源, 状态码 200, 如果没有修改只返回响应头, 状态码 304, 告知浏览器资源的本地缓存还可用.
If-Modified-Since 与 Last-Modified
Last-Modified 标记资源文件在服务器端最后被修改的时间.
If-Modified-Since 的值为上次请求资源文件时响应头字段 Last-Modified 的值, 在第二次请求时作为请求头发给服务器, 服务端通过 If-Modified-Since 字段来判断在这两次访问期间资源有没有被修改过. 如果有修改正常返回资源, 状态码 200, 如果没有修改只返回响应头, 状态码 304, 告知浏览器资源的本地缓存还可用.
Expires
Expires 是用来定义缓存到期时间的字段, 值为绝对时间.
有一个弊端: 它返回的是服务器的时间, 但判断的时候用的却是客户端的时间, 如果客户端时间与服务器 时间不一致, 则导致缓存时间判断出错.
同源策略
目的
同源政策的目的, 是为了保证用户信息的安全, 防止恶意的网站窃取数据.
定义
所谓 "同源" 指的是协议相同, 域名相同, 端口相同.
限制
无法向非同源地址发送 AJAX 请求(可以发送, 但浏览器会拒绝接受响应).
无法接触非同源网页的 DOM, 非同源网页之间无法进行通信.
无法读取非同源网页的 Cookie,LocalStorage 和 IndexedDB.
跨域手段
CORS
CORS 是跨源资源分享 (Cross-Origin Resource Sharing) 的缩写. 它是 W3C 标准, 属于跨源 AJAX 请求的根本解决方法. CORS 允许任何类型的请求. 整个 CORS 通信过程, 都是浏览器自动完成, 不需要用户参与.
webSocket
WebSocket 是一种通信协议, 使用 ws://(非加密)和 wss://(加密)作为协议前缀. 该协议不实行同源政策, 只要服务器支持, 就可以通过它进行跨源通信.
JSONP
JSONP 是服务器与客户端跨源通信的常用方法. 最大特点就是简单适用, 老式浏览器全部支持, 服务端改造非常小, 缺点是只能发 GET 请求.
实现思路: 网页通过添加一个 < script > 元素, 向服务器请求 JSON 数据, 服务器收到请求后, 将数据放在一个指定名字的回调函数里传回来.
CORS,WebSocket,JSONP 是解决限制 1 的.
只要跨域, 父窗口与子窗口之间就无法获取对方的 DOM, 无法通信. 为了解决这个问题, 有如下方法:
document.domain
如果两个网页一级域名相同, 只是次级域名不同, 浏览器允许通过设置 document.domain 共享 Cookie.
两个网页都需要设置相同的 document.domain 属性, 才可以共享 Cookie, 获取 DOM.
location.hash
URL 有一部分被称为 hash, 就是 #号及其后面的字符, 它一般用于浏览器锚点定位, 修改它不会产生 HTTP 请求.
父窗口可以把信息, 写入子窗口的片段标识符. 子窗口通过监听 hashchange 事件得到通知. 从而实现通信. 反之一样.
postMessage
window.postMessage 方法, 允许跨窗口通信, 不论这两个窗口是否同源.
postMessage 方法的第一个参数是具体的信息内容, 第二个参数是接收消息的窗口的源(origin), 即 "协议 + 域名 + 端口". 也可以设为 *, 表示不限制域名, 向所有窗口发送.
父窗口和子窗口都可以通过 postMessage 方法向对方发送消息.
父窗口和子窗口都可以通过 message 事件, 监听对方的消息. message 事件的参数是事件对象 event.
event.source: 发送消息的窗口; event.origin: 消息发向的网址; event.data: 消息内容
document.domain,location.hash,postMessage 是为了解决限制 2 和限制 3 的
重流与重绘
重流
简单说就是重新计算网页布局.
重绘
简单说就是根据新布局重新渲染网页. 所以, 重流必然导致重绘, 重绘不一定需要重流.
大多数情况下, 浏览器会智能判断, 将重流和重绘只限制到相关的子树上面, 最小化所耗费的代价.
作为开发者, 应该尽量设法降低重绘的次数和成本.
浏览器存储
sessionStorage 和 localStorage
它们除了保存期限的长短不同(sessionStorage 保存的数据用于浏览器的一次会话, localStorage 保存的数据长期存在), 其余完全相同.
它们也受同域限制. 每个域名的存储上限视浏览器而定, Chrome 是 2.5MB,Firefox 和 Opera 是 5MB,IE 是 10MB.
当储存的数据发生变化时, 会触发 storage 事件. 值得特别注意的是, 该事件不在导致数据变化的当前页面触发.
Cookie
它的容量很小(4KB), 缺乏数据操作接口, 并不推荐作为客户端储存.
拦截窗口的判断
主要利用 window.open 方法, 该方法用于新建另一个浏览器窗口, 并且返回该窗口对象. 如果返回 null 则打开失败.
- var newPop = window.open(url)
- if(!newPop){
- alert('您有默认程序阻止打开新窗口, 请关闭后再试')
- }
多窗口操作
window.top: 顶层窗口; window.parent: 父窗口; window.self: 当前窗口.
浏览器还提供一些特殊的窗口名, 供 open 方法,<a > 标签,<form > 标签等引用.
_top: 顶层窗口;_parent: 父窗口;_blank: 新窗口
下面代码就表示在顶层窗口打开链接.
<a href="somepage.html" target="_top">Link</a>
navigator 对象
window 对象的 navigator 属性, 指向一个包含浏览器信息的对象.
- navigator.userAgent // 返回浏览器的厂商和版本信息, 用来识别浏览器
- navigator.platform // 返回用户的操作系统信息.
- navigator.plugins // 返回一个类似数组的对象, 成员是浏览器安装的插件.
- navigator.language // 使用的语言, 用作国际化.
- navigator.geolocation // 返回一个 Geolocation 对象, 包含用户地理位置的信息.
Geolocation 对象
getCurrentPosition 方法, 用来获取用户的地理位置.
watchPosition 方法可以用来监听用户位置的持续改变, 使用方法与 getCurrentPosition 方法一样.
watchPosition 方法返回的标识符, 用于供 clearWatch 方法取消监听.
- var geolocation = navigator.geolocation
- function geoSuccess(event) {
- console.log(event.timestamp) // 返回获得位置信息的具体时间
- console.log(event.coords) // 一个对象, 包含了用户的位置信息
- console.log(event.coords.latitude) // 纬度
- console.log(event.coords.longitude) // 经度
- console.log(event.coords.accuracy) // 精度
- console.log(event.coords.altitude) // 海拔
- console.log(event.coords.altitudeAccuracy) // 海拔精度
- console.log(event.coords.heading) // 以 360 度表示的方向
- console.log(event.coords.speed) // 每秒的速度
- }
- function geoError(event) {
- console.log(event.code) // 表示错误类型
- console.log(event.message) // 表示错误信息
- }
- geolocation.getCurrentPosition(geoSuccess, geoError)
history 对象
back() 移动到上一个访问页面, 等同于浏览器的后退键.
forward() 移动到下一个访问页面, 等同于浏览器的前进键.
go() 接受一个整数作为参数, 移动到该整数指定的页面, 比如 go(1)相当于 forward(),go(-1)相当于 back().go(0)相当于刷新当前页面.
pushState() 在浏览历史中添加记录, 接受三个参数: 第一个参数为一个与指定网址相关的状态对象, 第二个为新页面的标题, 第三个为新的网址, 浏览器的地址栏将显示这个网址.
不会触发页面刷新, 只是导致 history 对象发生变化, 地址栏会有反应.
replaceState() 在浏览历史中修改记录, 参数与 pushState 保持一致.
state 返回当前页面的 state 对象.
参考资料
缓存详解 https://juejin.im/post/5a6c87c46fb9a01ca560b4d7#heading-15
前端跨域整理 https://juejin.im/post/5815f4abbf22ec006893b431#heading-8
跨域资源共享 CORS 详解 http://www.ruanyifeng.com/blog/2016/04/cors.html
同源政策 http://javascript.ruanyifeng.com/bom/same-origin.html#
来源: http://www.jianshu.com/p/1051b29dc61e