什么场景下需要跨tab通信? 有一些日常中很常见的场景,如果支持跨tab通信,可能能给用户更好的体验。
博客Dark Mode切换 想象你在浏览 Dan Abramov的博客 ,你同时打开了好几个tab学习一系列知识。夜晚来临,你将一个页面切换成了Dark Mode。当你阅读完这一篇去阅读下一篇时,页面却不是以Dark Mode呈现的。你不得不按下F5刷新页面来寻求一致的阅读体验。
需要频繁登录的CMS系统 想象你在网店管理系统中管理你网店中的商品,你打开了好几个tab,分别管理商品类型,商品详情以及商品库存。你正在管理你的商品详情,突然你的登录session过期,你点击重新登录。但是当你切换到商品库存页面时,你发现你依旧无法操作,需要再次登录。你不得已点击了登录按钮,和你辛苦编辑了10分钟但没有保存的商品库存说了拜拜。
以上场景其实无伤大雅,你的系统依旧运转,核心功能依旧正常。但是借助跨tab通信,你能给用户提供更好更顺滑的体验。
Cookie & IndexedDB 要实现数据的一致,很容易想到的就是统一的数据存储。在有后端加入的时候,后端其实就是前端的统一数据存储。在纯前端的环境下,比较常见的数据存储包括
cookie localStorage sessionStorage IndexedDB sessionStorage 由于只存活于单个tab session中,所以不能用于跨tab通信。localStorage 有其他的应用方式,下面会深入分析。所以在这个章节我们主要关注cookie和IndexedDB。
实现思路 实现思路其实非常简单,就是通过轮询数据源,来确保每个tab的数据都是最新的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // Cookie Way // Producer Tab, 当然你也可以用js-cookie这种库更高效的操作cookie document.cookie = "blabla" // Consumer Tab setInterval(() => { const cookie = document.cookie; //Use Cookie to do something doSomething(cookie) }, 1000) // IndexedDB way // Producer Tab const transaction = db.transaction(["customers"], "readwrite"); const objectStore = transaction.objectStore("customers"); customerData.forEach(function(customer) { const request = objectStore.add(customer); request.onsuccess = function(event) { // do some callback }; }); // Consumer Tab setInterval(() => { const transaction = db.transaction(["customers"]); const objectStore = transaction.objectStore("customers"); const request = objectStore.get("444-44-4444"); request.onsuccess = function(event) { doSomething(request.result.name); }; }, 1000) 需要注意的是,cookie的读写是同步的,在cookie比较大的时候可能会阻塞主线程造成页面卡顿。而IndexedDB的API都是异步的,所以不会有cookie同步读写的性能问题。
...