美文网首页
同源策略中,页面间如何通信?

同源策略中,页面间如何通信?

作者: 我没叫阿 | 来源:发表于2023-06-06 17:58 被阅读0次

    引言

    • 在浏览器中我们可以同时打开多个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))
    

    相关文章

      网友评论

          本文标题:同源策略中,页面间如何通信?

          本文链接:https://www.haomeiwen.com/subject/vjvgedtx.html