如何实现多 Tab 同步登陆和退出

一. 场景再现

  1. 前两天接到一个需求,要求实现类似于 B站 的那种,当我同时打开多个 Tab 标签的时候,如果我在某一个窗口退出了,那么其它窗口的登陆状态也需要同步退出。如下图,我同时打开了两个 tab

    如何实现多 Tab 同步登陆和退出_第1张图片
  2. 当我点击其中一个窗口的退出时,你会发现另外一个窗口也神奇的同步退出了。

  3. 经过查阅相关资料,比较简单的方法有两种,一个是 window.postMessage,另外一个就是监听 localStorage 的变化,接下来我会分别演示这两种方案。

二. 搭建一下基础样式

  1. 注意:样式方面,在这里我使用的是 UnoCSS ,将样式內联在了标签里,如果你还不了解这种写法,你可以点击下方的文章学习。不过即使你之前从未了解过 UnoCSS ,也不会影响你下面的阅读,因为样式不是本文的重点,并不影响整体阅读。
    手把手教你如何创建一个代码仓库
  2. 如果恰好你使用了 Unocss 那么你可以直接复制我下面的代码快速开始今天的知识。

    
    
    
    
  3. 如果你没有用到 Unocss,你也不用担心,因为我们的样式非常简单,页面只有三个元素。一个表示是否已经登陆的文案,然后剩下两个按钮,一个是打开新窗口的功能,一个是退出登陆的功能。

    如何实现多 Tab 同步登陆和退出_第2张图片

三. window.postMessage

  1. 我们快速书写一个打开新窗口的函数。

    如何实现多 Tab 同步登陆和退出_第3张图片
  2. 此时我们还需在当前页面挂载以后给 window 绑定一个事件来搭配 window.open 之后我们要做的事情。这里我们给 window 绑定了一个监听事件,事件的名称叫做 "message",回调函数中的参数 e 我们暂时不需要关系,我们继续往下进行代码书写。

    如何实现多 Tab 同步登陆和退出_第4张图片

    可以看到我们的 window.open 正确的打开了一个新的 tab
    如何实现多 Tab 同步登陆和退出_第5张图片
  3. 接下来我们编写我们的退出按钮的函数。

    如何实现多 Tab 同步登陆和退出_第6张图片

    首先很简单,它把我们的 isLogin 变量标记为 false,我们就可以通过观察 span 标签中的文案变化观察我们的状态。
    image.png
    另外一个重点,这里我们用到了 window.opener 这个属性,这个属性代表着它上一级的窗口。我们要向谁发生消息?上一级窗口对吧?调用 target?.postMessage 函数,这个函数第一个参数就是我们要发送的消息。我们就用 “退出” 字符串当作我们退出的信号吧。第二个参数是我们用 / 表示默认为当前的 origin 。届时上一级窗口的回调函数的事件对象就会收到我们的消息。
  4. 试验一下,可以很清楚的看到,我们第一个父窗口已经收到了来自子窗口的消息 “退出”,它是事件对象的 data属性的值。


    那么此时我们就可以判断,如果收到了退出的信号,那么我也跟着把 isLogin 变量的值改为 false,也实现退出的动作。

    如何实现多 Tab 同步登陆和退出_第7张图片
  5. 测试一下效果:

    如何实现多 Tab 同步登陆和退出_第8张图片

四. 监听 localStorage

  1. 关于 storage 事件,这里面有一个误区,希望读者不要被误导,这个事件无法监听 sessionStorage 的变化。在 MDN 的中文文档中,并没有特别明显指出这一点。

    如何实现多 Tab 同步登陆和退出_第9张图片

    而在英文文档中明确指出了这个十分关键的信息。

    如何实现多 Tab 同步登陆和退出_第10张图片

    知道了这个关键点,就知道为什么我要写明要使用 localStorage 了。

    原文地址: MDN Storage Event

  2. 其实这个事件的用法和上面的 “message事件” 非常类似。第一步,你只需把我们给 window 绑定的事件替换为 "storage" 即可。
    如何实现多 Tab 同步登陆和退出_第11张图片
  3. 然后修改我们的 logOut 函数。在执行的时候在 localStorage 里写入一个 isLoginfalse 的状态。(storage 只能写入字符串类型的值,所以需要 JSON 序列化一下,基础知识不过多赘述。)

    如何实现多 Tab 同步登陆和退出_第12张图片
  4. 可以看到,我们第二个 tab 退出的时候,第一个 tab 已经监听到了 storage 的变化了。



    我们看一下这个事件对象身上的信息,这里面有两个属性是我们需要的。一个是 key,也就是发生变化的值,另外一个是 newValue 代表我们刚刚设置的值。

    如何实现多 Tab 同步登陆和退出_第13张图片
  5. 知道了这些信息,我们就可以在事件的回调函数中做一些处理。

    如何实现多 Tab 同步登陆和退出_第14张图片
  6. 测试一下:

五. 总结

实现方法其实还挺简单的,在实际工作中,我们项目的实现就是将 token 存放到 localStorage 里,通过监听 token 的存在来实现多 tab 的同时退出和同时登陆。

其实还有别的方法,比如同时开启一个 webSocket,让后端搭配同步向 tab 发消息等。

你可能感兴趣的:(前端javascript)