了解 BFCACHE

firefox 1.5 开始在一个浏览器会话中通过内存来缓存整个网页,包括它们的javascript状态。在已访问的页面中使用前进和后退不会触发页面加载,并且 javascript的状态都会被保留。这个特点被称为 bfcache( back-forward cache), 它使得页面导航变得更加快速。这个缓存状态将一直保留直到用户关闭了浏览器。

有些情况下,firefox不会缓存页面。下面是一些firefox不缓存页面的常见原因:

页面使用了 unload 或者 beforeload 事件句柄
页面设置了 cache-control: no-store
网站采用了Https 并且至少设置如下一条:

(1)Cache-Control: no-cache

(2)Pragma: no-cache

(3)使用了Expires: 0 或者 Expires 的值被被设置为当前页面头date属性内时间的过去时间(除非Cache-Control: max-age=同时指定)

4.页面还未加载完成用户就从页面离开,或者其他原因(XMLHttpRequest)

  1. 该页面已运行索引型数据库的事务

  2. 顶级页面中包含框架(例如iframe),且框架中有此处列举的任何一条。

  3. 页面在框架中,用户通过这个框架加载了一个新的页面(这个情况下,当用户离开这个页面,最后插入一个这个框架的内容将会被缓存)

这种新的缓存机制改变了页面加载行为,web开发者可能想:

了解一个页面是否已经访问过(什么时候页面是从缓存中加载)
当用户从离开一个页面时定义页面的行为(同时还使得页面被缓存)

两个新的浏览器事件允许开发者这么做。

##新的浏览器事件

如果你使用这些新的事件,你的页面仍然会在其他浏览器中正确显示(我们已经测试过了早期版本的firefox,ie,opera 和 safari),当页面在firefox1.5中加载时就会使用这个新的缓存机制。

注意:10–2009 safari的开发者版本中增加了对这些新事件的支持。

标准的网页行为是这样的:

用户浏览这个页面
页面的脚本在页面加载时执行
页面加载完毕后,onload句柄触发

有些页面有第四步。如果页面使用了unload或beforeunload句柄,用户离开页面时会触发它们。如果unload句柄存在,页面就不会被缓存。

当用户浏览到缓存过的页面,页面的脚本和onload句柄不会运行(第2,3步),大多数情况下,这些脚本的效果将会被保留。

如果一个页面包含部分脚本在用户每次浏览到页面时都想继续运行,或者你想知道用户什么时候浏览到了一个缓存过的页面,可以使用新的 pageshow 事件。

如果当用户离开页面时有一些行为想要触发,你想利用这个新的缓存机制但并打算使用unload句柄时,可以使用新的pagehide事件。 pageshow event

这个事件和load事件类似,不同的是这个事件在页面加载后每次都会触发。(如果页面被缓存,load事件在firefox 1.5中不会被触发)页面首次加载时,pageshow事件会在load事件触发后运行。pageshow事件包含了一个名为 persisted的属性,值是 布尔,初始化加载时,这个属性的值是false(换句话说,页面如果被缓存,这个值就是true)。

在pageshow事件触发时加入你想在页面加载时每次都执行的脚本。

##pagehide event

如果你要定义用户离开页面的行为,但是又不希望使用unload事件(unload事件会使得页面不会被缓存),你可以使用新的pagehide事 件。类似pageshow,pagehide也使用了一个名叫persisted的属性,页面如果没有被缓存,值为false,反之为true。如果这个 值为false, unload句柄会在pagehide事件触发后立即执行。

在初始化加载页面时,firefox试图以相同的顺序来触发事件。框架处理的方式与顶级文档是相同的。如果页面包含框架,那么当缓存的页面加载时:

框架中的pageshow事件会在主文档的pageshow事件之后触发
当用户离开一个缓存过的页面,框架中的pagehide事件会在主文档的pagehide事件之前触发。
框架中的页面变化时,事件只会在这个框架中触发。

无视unload和beforeunload事件缓存页面

如果你希望在使用unload或者beforeunload事件的同时保留页面缓存机制,那么你可以在回到这个页面时在pageshow事件中添加他们。

window.addEventListener('pageshow', PageShowHandler, false);
window.addEventListener('unload', UnloadHandler, false);

function PageShowHandler() {
	window.addEventListener('unload', UnloadHandler, false);
}

function UnloadHandler() {
	window.removeEventListener('unload', UnloadHandler, false);
}

示例代码

下面的示例中页面同时使用了load和pageshow事件,页面的行为如下:

在firefox1.5以外的浏览器中,页面每次加载时均会发生:load事件触发onLoad方法,同时调用onpageshow方法
在firefox1.5中,页面首次加载时,load事件与其他浏览器一样。当persisted属性为true时,只有pageshow事件会触发。
在firefox1.5中,当页面从缓存中加载时,只有pageshow事件会触发。当persisted为true时,只有在onPageShow中的脚本才会执行。

在这个例子中:

页面加载时会显示当前的时间。时间会精确到毫秒,这样你就可以很方便地测试功能。
在页面首次加载时,鼠标会定位到name字段中。在firefox1.5内,当用户返回到这个页面,光标会停留在用户离开时所在的位置,在其他浏览器中,光标将被重新放置在name字段中。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<head>
<title>Order query Firefox 1.5 Example</title>
<style type="text/css">
body, p {
	font-family: Verdana, sans-serif;
	font-size: 12px;
 	}
</style>
<script type="text/javascript">
function onLoad() {
	loadOnlyFirst();
	onPageShow();
}

function onPageShow() {
//calculate current time
	var currentTime= new Date();
	var year=currentTime.getFullYear();
	var month=currentTime.getMonth()+1;
	var day=currentTime.getDate();
	var hour=currentTime.getHours();
	var min=currentTime.getMinutes();
	var sec=currentTime.getSeconds();
	var mil=currentTime.getMilliseconds();
	var displayTime = (month + "/" + day + "/" + year + " " +
		hour + ":" + min + ":" + sec + ":" + mil);
	document.getElementById("timefield").value=displayTime;
}

function loadOnlyFirst() {
	document.zipForm.name.focus();
}
</script>
</head>
<body onload="onLoad();" onpageshow="if (event.persisted) onPageShow();">
<h2>Order query</h2>

<form name="zipForm" action="http://www.example.com/formresult.html" method="get">
<label for="timefield">Date and time:</label>
<input type="text" id="timefield"><br>
<label for="name">Name:</label>
<input type="text" id="name"><br>
<label for="address">Email address:</label>
<input type="text" id="address"><br>
<label for="order">Order number:</label>
<input type="text" id="order"><br>
<input type="submit" name="submit" value="Submit Query">
</form>
</body>
</html>

与此相反,当这个页面没有监听pageshow事件,并且把所有的方法都放置在load事件中,则光标位置和时间都会被缓存。当用户返回这个页面时,显示将是缓存中的时间。

<script>
function onLoad() {
	loadOnlyFirst();

//calculate current time
	var currentTime= new Date();
	var year = currentTime.getFullYear();
	var month = currentTime.getMonth()+1;
	var day = currentTime.getDate();
	var hour=currentTime.getHours();
	var min=currentTime.getMinutes();
	var sec=currentTime.getSeconds();
	var mil=currentTime.getMilliseconds();
	var displayTime = (month + "/" + day + "/" + year + " " +
		hour + ":" + min + ":" + sec + ":" + mil);
	document.getElementById("timefield").value=displayTime;
}

function loadOnlyFirst() {
	document.zipForm.name.focus();
}
</script>
</head>

<body onload="onLoad();">

##开发firefox插件

firefox1.5的扩展需要开启这个缓存机制。当你在开发与firefox1.5及早期firefox版本兼容的扩展时,确保load事件会被缓存,pageshow事件不会被缓存。

posted @ 2016-05-09 17:57  wobblywhistle  阅读(487)  评论(0编辑  收藏  举报