监听本地存储,实现跨标签页通讯

76 阅读1分钟

浏览器有个storage事件,会在localStorage变化时触发,可以利用这点实现跨标签页通信

工具函数 util.js

// 发送消息
function sendMsg(type, payload) {
  // 加上@@是为了特殊化处理,防止和其他localStorage中的key冲突
  localStorage.setItem('@@' + type, JSON.stringify({
    payload,
    tmp: Date.now()  // 加时间戳是为了让value值每次都不一样,才能触发window上面的storage事件
  }));
}

// 监听消息
function listenMsg(callback) {
  const handler = (e) => {
    callback(e.key.substring(2), e.newValue);
  };

  window.addEventListener('storage', handler);

  // 返回一个取消订阅的函数,用于在Unmounted生命周期里面取消订阅
  return () => {
    window.removeEventListener('storage', handler);
  };
}

页面A: 监听消息 index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .container {
      display: flex;
      flex-direction: column;
    }

    .item-container {
      width: 200px;
      height: 50px;
      border: 1px solid #ccc;
      display: flex;
    }

    .item {
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px solid #ccc;
    }
  </style>
</head>

<body>
  <a href="./form.html" target="_blank">add</a>
  <div class="container"></div>
  <script src="./util.js"></script>
  <script>
    // 监听localStorage变化
    listenMsg((type, value) => {
      console.log('收到消息:', type, value);
      const { payload } = JSON.parse(value);

      // 发现是指定事件,做相应处理
      if (type === 'add-emp') {
        const $ = document.querySelectorAll.bind(document);
        const itemContainer = $('.container')[0];
        itemContainer.innerHTML += `<div class="item-container">
          <div class="item">${payload.name}</div>
          <div class="item">${payload.age}</div>
        </div>`;
      }
    });

    const data = [
      {
        name: 'rance',
        age: 19
      },
      {
        name: 'rance2',
        age: 19
      },
      {
        name: 'rance3',
        age: 19
      },
    ];

    let html = ``;
    for (let item of data) {
      html += `<div class="item-container">
      <div class="item">${item.name}</div>
      <div class="item">${item.age}</div>
    </div>`;
    }

    const $ = document.querySelectorAll.bind(document);
    const itemContainer = $('.container')[0];

    itemContainer.innerHTML = html;
  </script>
</body>

</html>

页面B: 发送消息 form.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div>
    name: <input type="text" id="name">
  </div>
  <div>
    age: <input type="text" id="age">
  </div>
  <button id="btn">add</button>
  <script src="./util.js"></script>
  <script>
    const name = document.querySelector('#name');
    const age = document.querySelector('#age');

    // 点击按钮发送消息
    document.querySelector('#btn').onclick = function(){
      sendMsg('add-emp', {
        name:name.value,
        age:age.value
      });
    }
  </script>
</body>

</html>