引言
- 在浏览器中我们可以同时打开多个Tab页,每个页面与页面之前又可以理解为一个“独立”的运行环境,即使是全局对象也不会再多个Tab间共享。但是有些时候我们需要让他们之间共享一些数据。比如:在浏览器打开酷狗音乐听歌的时候,第一次是新开了一个Tab页,而播放第二首歌的时候则是在原来的Tab里进行切换歌曲,这个时候就需要用到页面见得通信。
BroadCast Channel
- BroadCast Channel 可以帮我们创建一个用于广播的通信频道。当所有页面都监听同一频道的消息时,其中某一个页面通过它发送的消息就会被其他所有页面收到。它的API和用法都非常简单。
- 我们在A页面通过BroadcastChannel创建一个对象
const channel = new BroadcastChannel('music')
- 通过点击按钮触发它的postMessage事件
channel.postMessage({
musicName: '只因你太美'
})
- 在B页面里创建同样名字的对象
const channel = new BroadcastChannel('music');
channel.addEventListener('message', (event) => {
console.log(event); // 这里可以拿到通讯所传递的对象
});
LocalStorage
-
LocalStorage 作为前端最常用的本地存储,大家应该已经非常熟悉了;但
StorageEvent
这个与它相关的事件大家会比较陌生。 -
当 LocalStorage 变化时,会触发 storage 事件。利用这个特性,我们可以在发送消息时,把消息写入到某个 LocalStorage 中;然后在各个页面内,通过监听 storage 事件即可收到通知。
-
在触发事件(既传递消息)的时候,增加localStorage.setItem方法
let data = {
musicName: '只因你太美'
}
localStorage.setItem('ctc-msg', JSON.stringify(data));
- 在需要接受数据的页面,增加监听 storage 的方法
window.addEventListener('storage', function (e) {
console.log(e);
});
IndexedDB
- IndexedDB“全局性”(支持跨页面)的存储方案。
- 思路:消息发送方将消息存至 IndexedDB 中;接收方(例如所有页面)则通过轮询去获取最新的信息。
- 封装IndexedDB的方法
// 打开数据库链接
function openStore() {
const storeName = 'ctc_aleinzhou';
return new Promise(function (resolve, reject) {
if (!('indexedDB' in window)) {
return reject('don\'t support indexedDB');
}
const request = indexedDB.open('CTC_DB', 1);
request.onerror = reject;
request.onsuccess = e => resolve(e.target.result);
request.onupgradeneeded = function (e) {
const db = e.srcElement.result;
if (e.oldVersion === 0 && !db.objectStoreNames.contains(storeName)) {
const store = db.createObjectStore(storeName, {keyPath: 'tag'});
store.createIndex(storeName + 'Index', 'tag', {unique: false});
}
}
});
}
// 存储数据
function openStore() {
const storeName = 'ctc_aleinzhou';
return new Promise(function (resolve, reject) {
if (!('indexedDB' in window)) {
return reject('don\'t support indexedDB');
}
const request = indexedDB.open('CTC_DB', 1);
request.onerror = reject;
request.onsuccess = e => resolve(e.target.result);
request.onupgradeneeded = function (e) {
const db = e.srcElement.result;
if (e.oldVersion === 0 && !db.objectStoreNames.contains(storeName)) {
const store = db.createObjectStore(storeName, {keyPath: 'tag'});
store.createIndex(storeName + 'Index', 'tag', {unique: false});
}
}
});
}
// 读取数据
function query(db) {
const STORE_NAME = 'ctc_aleinzhou';
return new Promise(function (resolve, reject) {
try {
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
const dbRequest = store.get('ctc_data');
dbRequest.onsuccess = e => resolve(e.target.result);
dbRequest.onerror = reject;
}
catch (err) {
reject(err);
}
});
}
- 发送消息
let data = {
musicName:'只因你太美!'
}
openStore().then((db) =>saveData(db, null)).then(function (db) {
// 触发 saveData 的方法可以放在用户操作的事件监听内
saveData(db, data);
});
- 接收数据
openStore().then((db) => this.saveData(db, null)).then(function (db) {
setInterval(function () {
query(db).then(function (res) {
console.log(res);
});
}, 3000);
});
- 打开数据连接,初始化数据
openStore().then(db => saveData(db, null))
网友评论