概念定义
正常导航会销毁页面。bfcache 把整页——DOM、JavaScript 堆、滚动位置——冻结保存,后退或前进时毫秒级恢复,不重新加载、不重新执行、不重新请求。对用户而言,上一个页面从未离开。
工作机制
导航时页面进入缓存;恢复触发 persisted 为 true 的 pageshow 事件。失去资格的因素包括 unload 处理器(多数引擎)、打开中的 IndexedDB 事务、部分场景的 WebSocket 或 WebRTC 状态,以及主文档 Cache-Control: no-store。
使用场景
用户在列表页与详情页之间往返的内容站。应埋点 pageshow 探测命中率,用 pagehide 与 visibilitychange 替代 unload,并在恢复时刷新定时器、购物车等易变 UI。
常见误区
恢复的页面会让脚本“接着想”:长轮询可能已死、缓存认证可能过期。广告可见性与分析需要恢复感知的事件处理,避免重复计数或漏计曝光。测试时应打开暴露驱逐原因的浏览器标记。
代码示例
<nav aria-label="Primary navigation">
<button class="menu-toggle"
aria-expanded="false"
aria-controls="main-menu"
aria-label="Toggle navigation menu">
<span class="hamburger"></span>
</button>
<ul id="main-menu" class="menu" role="menubar">
<li role="none">
<a href="/" role="menuitem" aria-current="page">Home</a>
</li>
<li role="none">
<a href="/products" role="menuitem">Products</a>
</li>
<li role="none">
<a href="/about" role="menuitem">About</a>
</li>
<li role="none">
<a href="/blog" role="menuitem">Blog</a>
</li>
<li role="none">
<a href="/contact" role="menuitem">Contact</a>
</li>
</ul>
</nav>
<nav aria-label="Breadcrumb">
<ol class="breadcrumb">
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li aria-current="page">Details</li>
</ol>
</nav>
<style>
.menu { list-style: none; display: flex; gap: 1rem; }
.menu a { text-decoration: none; padding: 0.5rem 1rem; }
.menu a[aria-current="page"] { font-weight: bold; border-bottom: 2px solid currentColor; }
.breadcrumb { list-style: none; display: flex; gap: 0.5rem; }
.breadcrumb li:not(:last-child)::after { content: " > "; }
</style>
public class StringBuilderManipulation {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(64);
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println("Built: " + sb);
sb.insert(5, " Java");
System.out.println("After insert: " + sb);
sb.delete(5, 10);
System.out.println("After delete: " + sb);
sb.replace(0, 5, "Hi");
System.out.println("After replace: " + sb);
sb.reverse();
System.out.println("Reversed: " + sb);
String csv = String.join(", ",
"Apple", "Banana", "Cherry", "Date");
System.out.println("CSV: " + csv);
String formatted = String.format(
"Name: %s, Age: %d, Score: %.2f",
"Alice", 30, 95.5
);
System.out.println(formatted);
String stripped = " padded ".strip();
System.out.println("Stripped: '" + stripped + "'");
}
}