浏览器页面间通信

361 阅读2分钟

介绍

我们在做移动端网站开发的时候,经常会遇到同一个网站打开两个网页同时这两个网页之间需要同步数据的情况。比如在订单列表页面,打开订单详情页面,之后对订单详情进行操作,返回订单列表,订单列表页面并不会刷新。因为很多移动端浏览器都是通过新建webview来打开新的链接,返回的时候直接关闭新的webview,而列表页面不会收到任何的通知。所以会出现列表与详情数据不同步的问题。

这个问题可以抽象为两个同源页面之间的信息通讯问题。而我们常见的页面页面间通信的技术手段有BroadCast ChannelService WorkerSharedWorkerLocalStorage等等。

但我们网站对低版本浏览器兼容性要求比较高,所以最后我们选择了LocalStorage方式进行封装。

原理

当localStorage值改变的时候,会触发window上面的storage的event事件。所以我们可以通过下面的语法来监听storage值的变化。

addEventListener('storage', (event) => { });
onstorage = (event) => { };

event有以下几个值:

key: 变化的属性名称

newValue: 变化后的值

oldValue: 变化前的值

storageArea: 被操作的storage对象

url: key发生改变的对象所在文档的URL地址

示例:

// page1
localStorage.setItem('message',JSON.stringify({
    message: '消息'from: 'Page 1',
    date: Date.now()
}))

// page2
window.addEventListener("storage", function(e) {
    console.log(e.key, e.newValue, e.oldValue)
});

在线Demo

songjiachao.github.io/browser-tab…

Demo

browser-tab-emitter

为了让方案更加通用,避免每个地方都去重复声明和调用这样的代码,我们封装了一个插件browser-tab-emitter

github.com/songjiachao…

安装

from NPM

npm i browser-tab-emitter

or if you use yarn

yarn add browser-tab-emitter

from CDN

<script src="https://cdn.jsdelivr.net/npm/browser-tab-emitter@1.0.5/dist/index.global.js"></script>

🛠 使用

client1.js

// npm install need, cdn way has been installed in global (window)
import BrowserTabEmitter from 'browser-tab-emitter'

const bte = new BrowserTabEmitter({
  // prefix: 'bte:'  // optional,default 'bte:'
})

// 绑定事件
bte.on('event1', (data) => {
  this.input1 = data
})

client2.js

import BrowserTabEmitter from 'browser-tab-emitter'
const bte = new BrowserTabEmitter()
// emit event
bte.emit('event1', data)