phpstudy页面不存在_跨页面的通信解决方案

文章背景

通信,这个词我相信大家一定不陌生。SPA中有许多的实现如eventEmitter、Props、context以及优秀的Redux、Vuex库。但是本文主要讨论的是跨页面的通信

为什么写

工作中遇上了这么个需求,需要在A页面点击后打开一个新页面B,并触发EventEmitter打开侧边栏。当然解决需求不难,但是希望能得到一个完整的解决方案,而不仅仅针对单一需求。最后罗列了一下场景:

  1. Tab/页面AB均已打开,两页面之间进行数据传递

2. 在页面A中操作打开新页面B、让B知道不仅仅是打开就完事了,还得干活。

3. 待补充。。。

所以针对这几种情况做了一些调研。项目中大多采用URL携参数来解决场景2,此外针对场景1没有落地的需求。

那么就得给花了的时间一个交代,也希望能有幸帮上之前不了解的web developer吧。

现有解决方案

一、localStorage

场景:

1. 页面AB均已存在,可以通过onstorage监听共享域获取值。

2. 页面A存在,点击打开新页面B后进行通信。可以在B页面内通过localStorage.getItem(key)获取值。

d3b3d3c905ed1b681c9ce97283b20f68.png

注意点:

  • 页面A修改localStorage,不会触发onstorage事件
  • 如果localStorage值未发生变化,不会触发onstorage事件
  • 部分浏览器隐身模式下,无法设置localStorage。如safari

优势:浏览器支持效果好、API直观。onstorage的设定,就像是为了页面间通信做的准备。

二、url

通过url中携带query参数,在B页面初始化时获取参数。

场景:仅可用于A页面下打开新页面B的场景

优势:浏览器支持效果好、持久化、无需配置。

缺陷:语义不明的内部状态暴露在url中不合理 ,同时数据较多时导致url臃肿。

三、postMessage

A页面通过window.open获取B页面的句柄。通过otherWindow.postMessage传递数据,在B页面通过onmessage获取A页面传递的参数,也可以通过e.source.postMessage传递信息给A页面。

场景:

  1. AB页面均存在时,通过postMessage与onmessage组合即可
  2. A存在,打开新页面B进行传递时,A页面需要监听B页面完成message注册后才能传递。

bc2da7497375444c52939cb5e0db2844.png

注意点

  • Window.open方法的第二个参数为设置子页面的name,再次调用open方法会触发同name属性子页面刷新。
  • 该方案允许跨源传递数据,注意数据的安全性。如果知道通信窗口的origin属性,建议配置第二个参数进行限制接收方(推荐配置)
  • 异步请求后window.open会被浏览器拦截,当然也可以通过改变otherWindow.location属性来避开

优点:点对点通信,跨域的场景下可以使用

劣势:使用面小,高度依赖window.open。比如:通过a标签打开B页面,无法使用。

四、 BroadCast channel

它的出现,是为了解决postMessage只能点对点通信的问题,广播形式能够在同域的页面下进行一对多的通信。通过相同的口令连接到同一个频道(像是面对面建群?)

场景:

  1. AB页面均存在,可通过onmessage与postMessage随意通信,处理
  2. 打开新页面B,需要监听B页面完成message注册后才能传递。

87dc7cb55975042eff5d3884dc3944f8.png

优点:实现一对多的数据传递(同名频道内),API直观。功能相比下更为全面

缺点:浏览器支持效果如下图,不乐观。

bea390b31000ecc374fbbc3f33c60c52.png

五、cookie

类似于localStorage的低配版,使用document.cookies保存。(仅为可能性讨论,不推荐)

场景:

  1. AB页面都存在,只能通过轮询检查cookie是否变化。。。emmm
  2. 打开新页面B进行通信,问题不大,同样在初始化后,获取cookie值进行处理

优点:。。。

缺点:cookie自身的特殊性,谁也不希望每次请求都带上一堆不相干的参数。。

六、通过window.***绑定参数

想法来自于:突发奇想。方法过于简单粗暴,通过B页面的window.opener.***获取到参数。但是不太推荐。因为这个方案只是突发奇想,解决的过程不优雅,无法形成统一的解决方案。

62bfaba884c863ec2614ab18cc34fd20.png

场景:仅适用于打开新页面B传递参数

优点:谁也顶不住的简单方便

缺点:称不上解决方案,过于hack。

其他方案

sharedworker

该功能的设计是页面间解决共享计算逻辑,但是也可以具有通信的手段,所以列出来:

6a5e2de24a523a95eb7db00cebfa91f0.png

场景:符合上述2种场景。

优点:异步处理,不占用主线程。

servieWorker

PWA的实现基础,主要用于处理网络,离线体验。可用于通信,但是不好用。附mozilla链接,感兴趣可以看看

Service Worker API​developer.mozilla.org
4333bc611af6270d8df17eb9a31f3d3c.png

浏览器数据库技术

调研中感觉在前端开发时已经不仅仅是js了,跨页面的通信在浏览器端都出现了许多方案。如下面介绍的sql语言

indexDB

数据存储技术,相比与localStorage来说对JS更友好,支持null、undefined、结构化数据(文件、blob)等所有数据类型。同时也支持离线使用。

场景:支持数据共享,若要即时通信,需要搭配轮询

优点:功能更为全面,提供索引实现高性能的查询。支持所有js类型的存储、支持好

缺点:没有监听事件无法用于即时通信。数据库对于前端来说相对陌生。

websql

浏览器端数据库(关系型),不过已经废弃,由indexDB取代了

总结

上面列举了目前已有的解决方案(不包含服务端如SSE、Websocket)。

在选择的技术,主要考量的三个方面:

1、兼容性。包括浏览器支持度、对历史代码的影响程度

2、通用性。能否覆盖需求、是否具有拓展性

3、便捷性。开发便捷程度

主要讨论下PostMessage、broadCastChannel。

在了解boradCastChannel时,抛开浏览器支持性来说,是个不错的解决方案。即时通信、随时关闭频道、不会产生因为LocalStorage不及时清理而引起的问题。

如场景2描述的:如A页面内打开B页面并存储了值,在B初始化时获取值并打开抽屉。若没能及时清理,会造成每次打开B页面都会打开抽屉。即使在B初始化后清理,也可能因为B页面未打开便关闭,造成未清理。

postMessage:点对点的通信,局限性很大。但是针对需求来说是完美cover的,但是无法对其进行扩展、如独立页面间的互相通信。所以无法因为符合需求就引入这种解决方案,而是需要与项目的解决方案保持一致。

以上分析后,符合笔者需要的解决方案为:localStorage

当然缺陷都是可以补齐的,通过window.onclose监听搭配B页面初始化后清理存储值,当然方法记得多加注释。

感想

当然对于调研方案的人来说,花了很多时间收集、对比但是最后用回了老技术,心里是有些失落的,似乎毫无提升。但是往往都是如此、就像发现了多彩的蘑菇、但是多半是有毒的。也许要等到毒性可控的时候,才会因为它的鲜美被人们接受。

总而言之,了解新方案,总是没坏处的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值