若要实现两个互不相关的通源tab页面通信,可以使用一种比较巧妙的方式:localstorage。localStorage的存储遵循同源策略,因此同源的两个tab页面可以通过这种共享localStorage的方式实现通信,通过约定localStorage的某一个itemName,基于该key值的内容作为“共享硬盘”方式通信。
HTML5提供了storage事件,通过window对象监听storage事件,会侦听到localStorage对象的变化事件(setItem和removeItem)。因此通过事件可以完成高效的通信机制。
A 页面 window.addEventListener("storage", function(ev){ if (ev.key == 'message') { // removeItem同样触发storage事件,此时ev.newValue为空 if(!ev.newValue) return; var message = JSON.parse(ev.newValue); console.log(message); } }); function sendMessage(message){ localStorage.setItem('message',JSON.stringify(message)); localStorage.removeItem('message'); } // 发送消息给B页面 sendMessage('this is message from A');
B 页面 window.addEventListener("storage", function(ev){ if (ev.key == 'message') { // removeItem同样触发storage事件,此时ev.newValue为空 if(!ev.newValue) return; var message = JSON.parse(ev.newValue); // 发送消息给A页面 sendMessage('message echo from B'); } }); function sendMessage(message){ localStorage.setItem('message',JSON.stringify(message)); localStorage.removeItem('message'); }
发送消息采用sendMessage函数,该函数序列化消息,设置为localStorage的message字段值后,删除该message字段。这样做的目的是不污染localStorage空间,但是会造成一个无伤大雅的反作用,即触发两次storage事件,因此我们在storage事件处理函数中做了if(!ev.newValue) return;
判断。
当我们在A页面中执行sendMessage函数,其他同源页面会触发storage事件,而A页面却不会触发storage事件;而且连续发送两次相同的消息也只会触发一次storage事件。
通过这种方式,可以实现同源下的两个tab页通信