itab标签页新建窗口没问题,但是打开浏览器打开新标签但是出现新窗口一开始的时候就是不行,什么方法都试过了?

最近,相信大家一定被这么个动效给刷屏了:以至于,基于这个效果的二次创作层出不穷,眼花缭乱。基于跨窗口通信的弹弹球:基于跨窗口通信的 Flippy Bird:我也尝试制作了一个跨 Tab 窗口的 CSS 动画联动,效果如下:代码不多,核心代码 200 行,感兴趣的可以戳这里:Github - broadcastAnimation当然,本文的核心不是去一一剖析上面的效果具体的实现方式,而是讲讲其中比较关键的一个技术点:而是应用如何在多窗口下进行互相通信。所谓多窗口下进行互相通信,是指在浏览器中,不同窗口(包括不同标签页、不同浏览器窗口甚至不同浏览器实例)之间进行数据传输和通信的能力。当然,本文我们探讨的是纯前端的跨 Tab 页面通信,在非纯前端的方式下,我们可以借助诸如 Web Socket 等方式,藉由后端这个中间载体,进行跨页面通信。因此,本文我们更多的重心将放在,如何基于纯前端技术,实现多窗口下进行互相通信。为了实现跨窗口通信,它应该需要具备以下能力:数据传输能力:能够将数据从一个窗口发送到另一个窗口,以及接收来自其他窗口的数据。实时性:能够实现实时或近实时的数据传输,以便及时更新不同窗口的内容。安全性:确保通信过程中的数据安全,防止恶意窃取或篡改通信数据。当然,这个不是本文讨论的重点,但是是实际应用中不应该忽视的一个重点。方式一:Broadcast Channel()Broadcast Channel 是一个较新的 Web API,用于在不同的浏览器窗口、标签页或框架之间实现跨窗口通信。它基于发布-订阅模式,允许一个窗口发送消息,并由其他窗口接收。其核心步骤如下:创建一个 BroadcastChannel 对象:在发送和接收消息之前,首先需要在每个窗口中创建一个 BroadcastChannel 对象,使用相同的频道名称进行初始化。发送消息:通过 BroadcastChannel 对象的 postMessage() 方法,可以向频道中的所有窗口发送消息。接收消息:通过监听 BroadcastChannel 对象的 message 事件,可以在窗口中接收到来自其他窗口发送的消息。同时,Broadcast Channel 遵循浏览器的同源策略。这意味着只有在同一个协议、主机和端口下的窗口才能正常进行通信。如果窗口不满足同源策略,将无法互相发送和接收消息。因为有同源限制,我们需要起一个服务,这里我基于 Vite 快速起了一个 Vue 项目,简单的基于 .vue 文件下进行一个演示。其核心代码非常简单: 这里,我们的核心逻辑在于:createBroadcastChannel() 函数用于创建一个 BroadcastChannel 对象,并设置消息处理函数。sendMessage(data) 函数用于向 BroadcastChannel 发送消息。handleMessage(event) 函数用于处理接收到的消息。resizeEventBind() 函数用于监听窗口大小变化事件,并在事件发生时获取当前元素的位置信息,并通过 sendMessage() 函数发送位置信息到 BroadcastChannel。getCurPos() 函数用于计算当前元素相对于显示器窗口右上角的距离。在 onMounted() 生命周期钩子中,调用了 createBroadcastChannel() 和 resizeEventBind() 函数,用于在组件挂载后执行相关的初始化操作。这样,当我们同时打开两个窗口,移动其中一个窗口,就可以向另外一个窗口发生当前窗口希望传递过去的信息,在本例子中就是 #j-main 元素距离显示器右上角的距离。假设 #j-main 只是一个在浏览器正中心矩形,我们同时打开两边的控制台,看看会发生什么:可以看到,如果我们同时打开两个一个的页面,当触发右边页面的 Resize,左边的页面会收到基于 broadcastChannel.onmessage = handleMessage 接收到的信息,反之同理。而一个完整的 Event 信息如下:譬如,传递过来的信息放在 data 属性内、同时也可以获取当前的的 Broadcast Name 等。基于 BroadcastChannel,就可以实现每个 Tab 内的核心信息互传, 可以得知当前在线设备数,再基于这些信息去完成我们想要的动画、交互等效果。这里的核心点,还是:数据向其他 Tab 页面传递的能力Tab 页面接受其他页面传递过来的数据的能力其本质就是一个数据共享池子。方式二:SharedWorker API好,介绍完 Broadcast Channel(),我们再来看看 SharedWorker API。SharedWorker API 是 HTML5 中提供的一种多线程解决方案,它可以在多个浏览器 TAB 页面之间共享一个后台线程,从而实现跨页面通信。与其他 Worker 不同的是,SharedWorker 可以被多个浏览器 TAB 页面共享,且可以在同一域名下的不同页面之间建立连接。这意味着,多个页面可以通过 SharedWorker 实例之间的消息传递,实现跨 TAB 页面的通信。它的实现与上面的 Broadcast Channel 非常类似,我们来看一看实际的代码: 简单描述一下,上面也说了,跨 Tab 页通信的核心在于数据向外的发送与接收的能力:initWorker() 方法中,使用 worker = new SharedWorker('/shared-worker.js', 'tabWorker') 创建了一个 SharedWorker , 后面每一个被打开的同域浏览器 TAB 页面,都是共享这个 Worker 线程,从而实现跨页面通信基于 worker.port.postMessage(data)实现数据的传输基于 worker.port.onmessage = function() {} 实现传输数据的监听当然,上面有引入一个 /shared-worker.js,这个是需要额外定义的,一个极简版本的代码如下://shared-worker.js const connections = []; onconnect = function (event) { var port = event.ports[0]; connections.push(port); port.onmessage = function (event) { // 接收到消息时,向所有连接发送该消息 connections.forEach(function (conn) { if (conn !== port) { conn.postMessage(event.data); } }); }; port.start(); }; 简单解析一下,下面对其进行解析:上面的代码中,定义了一个数组 connections,用于存储与 SharedWorker 建立连接的各个页面的端口对象;onconnect 是事件处理程序,当有新的连接建立时会触发该事件;在 onconnect 函数中,通过 event.ports[0] 获取到与 SharedWorker 建立的连接的第一个端口对象,并将其添加到 connections 数组中,表示该页面与共享 Worker 建立了连接。在连接建立后,为每个端口对象设置了 onmessage 事件处理程序。当端口对象接收到消息时,会触发该事件处理程序。在 onmessage 事件处理程序中,通过遍历 connections 数组,将消息发送给除当前连接端口对象之外的所有连接。这样,消息就可以在不同的浏览器 TAB 页面之间传递。最后,通过调用 port.start() 启动端口对象,使其开始接收消息。总而言之,shared-worker.js 脚本创建了一个共享 Worker 实例,它可以接收来自不同页面的连接请求,并将接收到的消息发送给其他连接的页面。通过使用 SharedWorker API,实现跨 TAB 页面之间的通信和数据共享。同理,我们来看看基于 Worker 的数据传输效果,同样是简化 DEMO,当 Resize 窗口时,向另外一个窗口发送当前窗口下 #j-main 元素的坐标:可以看到,如果我们同时打开两个一个的页面,当触发右边页面的 Resize,左边的页面会利用 worker.port.onmessage = function() {} 收到基于 worker.port.postMessage(data) 发送的信息,反之同理。而一个完整的 Event 信息如下:可以看到,在 SharedWorker 方式中,传输数据与 Broadcast Channel 是一样的,都是利用 Message Event。简单对比一下:SharedWorker 通过在多个Tab页面之间共享相同的 Worker 实例,方便地共享数据和状态,SharedWorker 需要多定义一个 shared-worker.js;Broadcast Channel 通过向所有订阅同一频道的 Tab 页面广播消息,实现广播式的通信。兼容性方面,到今天(2023-11-26),broadcast Channel 看着是兼容性更好的方式:另外,需要注意的是,两个方法都使用了 postMessage 方法。window.postMessage() 方法可以安全地实现跨源通信。并且,本质上而言,单独使用 postMessage 就可以实现跨 Tab 通信。但是,单独使用 postMessage 适合简单的点对点通信。在更复杂的场景中,Broadcast Channel 和 SharedWorker 提供更强大的机制,可简化通信逻辑,有更广泛的通信范围和生命周期管理。Broadcast Channel 的通信范围是所有订阅该频道的窗口,而 SharedWorker 可在多个窗口之间共享状态和通信。方式三:localStorage/sessionStorageOK,最后一种跨 Tab 窗口通信的方式是利用 localStorage 、sessionStorage 本地化存储 API 以及的 storage 事件。与上面 Broadcast Channel、SharedWorker 稍微不同的地方在于:localStorage 方式,利用了本地浏览器存储,实现了同域下的数据共享;localStorage 方式,基于 window.addEventListener('storage', function(event) {})事件实现了 localStore 变化时候的数据监听;简单看看代码: 同样的简单解析一下:每次页面初始化时,都会首先有一个 initLocalStorage 过程,用于给当前页面一个唯一 ID 标识,并且存入 localStorage 中每次页面 resize,将当前页面元素 #j-main 的坐标值,通过 ID 标识当 Key,存入 localStorage 中其他页面,通过 window.addEventListener('storage', (event)=> {}) 监听 localStorage 的变化交互传输结果,与上述两个动图是一致的,就不额外贴图了,但是基于 storage 事件传输的值有点不一样,我们展开看看:我们通过 window.addEventListener('storage', (event)=> {}) ,可以拿到此次变化的 localStorage key 是什么,前值 oldValue 与 newValue 等等。当然,由于 localStorage 存储过程只能是字符串,在读取的时候需要利用 JSON.stringify 和 JSON.parse 额外处理一层,调试的时候需要注意。虽然看起来这种方式最不优雅,但是结合兼容性一起看, localstorage 反而是兼容性最好的方式。在数据量较小的时候,性能相差不会太大,反而可能是更好的选择。我基于上面三种方式:Broadcast Channel、SharedWorker 与 localStorage,都实现了一遍下面这个跨 Tab 页的 CSS 联动动画:三种方式的代码都不多,感兴趣的可以戳这里:Github - broadcastAnimation实际应用思考当然,上面的实现其实有很大一个瑕疵。那就是我们只顾着实现通信,没有考虑实际应用中的一些实际问题:如何确定何时开始通信?Tab 页频繁的开关,如何知道当前还有多少页面处于打开状态?基于实际应用,我们需要基于上述 3 种方式,进一步细化方案。上面,为了方便演示,每次传输数据时,只传输动画需要的数据。而实际应用,我们可以需要细化整个传输数据,设定合理的协议。譬如:{ // 传输状态: // 1 - 首次传输 // 2 - 正常通信 // 3 - 页面关闭 status: 1 2 3, data: {} } 接收方需要基于收到信息所展示的不同的状态,做出不同的反馈。当然,还有一个问题,我们如何知道页面被关闭了?基于组件的 onUnmounted 发送当前页面关闭的信息或者基于 window 对象的 beforeunload 事件发送当前页面关闭的信息?这些信息都有可能因为 Tab 页面失活,导致关闭的信息无法正常被发送出去。所以,实际应用中,我们经常用的一项技术是心跳上报/心跳广播,一旦建立连接后,间隔 X 秒发送一次心跳广播,告诉其他接收端,我还在线。一旦超过某个时间阈值没有收到心跳上报,各个订阅方可以认为该设备已经下线。总而言之,跨 Tab 窗口通信应用在实际应用的过程中,我们需要思考更多可能隐藏的问题。跨 Tab 窗口通信应用场景当然,除了最近大火的跨 Tab 动画应用场景,实际业务中,还有许多场景是它可以发挥作用的。这些场景利用了跨 Tab 通信技术,增强了用户体验并提供了更丰富的功能。以下是一些常见的应用场景:实时协作:多个用户可以在不同的 Tab 页上进行实时协作,比如编辑文档、共享白板、协同编辑等。通过跨Tab通信,可以实现实时更新和同步操作,提高协作效率。譬如这个:多标签页数据同步:当用户在一个标签页上进行了操作,希望其他标签页上的数据也能实时更新时,可以使用跨 Tab 通信来实现数据同步,保持用户在不同标签页上看到的数据一致性。跨标签页通知:在某些场景下,需要向用户发送通知或提醒,即使用户不在当前标签页上也能及时收到。通过跨 Tab 通信,可以实现跨页面的消息传递,向用户发送通知或提醒。多标签页状态同步:有些应用可能需要在不同标签页之间同步用户的状态信息,例如登录状态、购物车内容等。通过跨 Tab 通信,可以确保用户在不同标签页上看到的状态信息保持一致。页面间数据传输:有时候用户需要从一个页面跳转到另一个页面,并携带一些数据,通过跨Tab通信可以在页面之间传递数据,实现数据的共享和传递。举几个实际的例子:某系统是一个国际化电商的仓库管理系统,系统能切换到全球各地不同的仓库进行数据操作,当用户打开了页面后,又新开了一个 Tab 页面,并且切换到另外一个仓库进行操作。当用户重新回到第一个打开的页面时,为了防止用户错误操作数据(前端界面是一致的,可能忘记了自己切换过仓库),通过弹窗提醒用户你已经切换过仓库;某音乐播放器 PC 页面,在列表页面进行歌曲播放点击,如果当前没有音乐播放详情页,则打开一个新的播放详情页。但是,如果页面已经存在一个音乐播放详情页,则不会打开新的音乐播放详情页,而是直接使用已经存在的播放详情页面;系统有与列表页与内容页,在内容页点击已阅,如果用户同时打开了上级列表页,要取消列表页关于该内容页的未读的提示;总之,跨 Tab 窗口通信在实时协作、数据同步、通知提醒等方面都能发挥重要作用,为用户提供更流畅、便捷的交互体验。最后本文只罗列了 3 种较为常见,适用性强的方式。除去本文罗列的方式,肯定还有其他方式能够实现跨 Tab 通信。譬如,基于 Window: opener property 配合 postMessage 也可以实现跨 Tab 窗口通信,但是这种通信仅仅适用于当前窗口以及通过当前窗口新开的窗口之间的通信。更多有意思的方式,期待大家的补充与探索。好了,本文到此结束,希望对你有帮助 :)如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
你还在为苹果自带的safari浏览器打不开网页而苦恼吗,接下来的答案会帮助你解决苦恼。苹果自带safari浏览器的设备分为两种:移动端、PC端。因此不同设备出现safari浏览器打不开网页的情况需要具体问题具体分析。最简单的问题往往最容易被我们忽视,所以safari浏览器无论在移动端或者PC端打开网页,首先务必请先检查:1、网络连接是否正常2、网站地址是否完整无误。接下来我会分别从移动端、PC端使用safari浏览器打不开的角度来分析问题解决问题。【移动端使用safari浏览器】一、网络信号太“LOW”。safari浏览器登录网站打不开可能是受制于我们差劲的网络信号,设备在使用中常连接两种网络信号,一种是移动数据,一种是WIFI(无线局域网)。(1)移动数据移动数据是GPRS流量(通用无线分组业务),想要正常使用GPRS流量,所在的地方必须要覆盖移动网络,移动网络的覆盖会受到通信环境的影响,比如你正处在某个小树林爬山或者乘坐的汽车正通过隧道,都会导致信号不稳定,这种情况你就需要移步到网络信号正常的位置在尝试safari浏览器登陆网站。(2)WIFI说道Wi-Fi相信大家都不会陌生了,它是一种允许电子设备连接到一个无线局域网(WLAN)的技术,WLAN通常有两种类型:公共网络、自建网络。公共网络的情景有以下几种:汽车、火车站、咖啡厅等公共活动空间可连接的wifi网络,有的需要手机号发短信验证后使用,有的则是获取账号密码登陆后才可使用。这类网络连接的用户及数量多,WIFI信号相对不稳定,safari浏览器登录网站自然打开缓慢,这个时候我们可以将WIFI切换至移动数据在打开网页。自建网络:普遍以家庭式网络为主,宽带账号密码登陆或启动猫自动登陆,路由器搭接后可使用的局域网络。最常见的情景是同时多个设备连接家里的WIFI,网速变慢,这时可以将多余设备从局域网络中移除。又或者是路由器的位置距离你所处的位置中间阻碍物过多,也会让信号变弱。遇到自建网络上述情况试着关闭WIFI,重新打开WIFI并连接,如果发现设备的WIFI过多,删除其中一个无用的即可。所以当我们使用safari浏览器时,需要根据不同的网络类型来做出应对。二、路由器“太累了”。safari浏览器打不开网页可能与路由器开启时间过长有一定关系,路由器启动之后,很少有人会记得在不使用的期间将其关闭,大多朋友都会放任路由器一直开启工作。路由器长时间的负荷致使电子元件变热,出现自动暂停工作的情况从而网页打不开。解决办法:关闭路由器,等待几分钟在开启,设备在重新连接WIFI登录网页。三、Safari访问网络未开启如safari浏览器登录网页显示不允许访问网络的情形,首先在设备“设置”应用中找到无线局域网(蜂窝数据),打开“使用无线局域网与蜂窝移动的应用”,找到Safari后看Safari访问网络是否是打开的,如果未打开,将它打开即可。四、系统内部冲突系统内部冲突发生后,safari浏览器也无法打开网页。解决办法:找到设备中的“飞行模式”关闭后在重新打开,然后在尝试用safari浏览器打开网页看是否正常。五、还原网络设置还原网络设置会把之前使用过的WIFI信息全部抹除,下次连接WIFI的时候需要重新输入密码。步骤:设备桌面“设置”应用--通用--还原--还原网络设置--重置后在重新输入密码连接WIFI。六、终极大招迫不得已的情况下,请记得把设备中的数据备份好在抹除数据刷机,如果之后在设备上找不到Safari 浏览器,可以在当前设备中检查“屏幕使用时间”或者“访问限制”是否禁用了Safari 浏览器。如果依然没有,就到 App Store 中重新下载。【PC端使用safari浏览器】一、PC端flish插件未安装完整通常我们登陆的网页是以flish形式展现的,往往在安装过程中下载flish插件到一半的时候中断退出了或者下载完成后未重启电脑等情形都会让我们误以为flish插件已经安装好。而当我们用safari浏览器登录网页进不去时,往往会忽略flish插件未安装完整的问题。下面整理的是检查flish插件是否安装的步骤,帮助大家排查这一问题。(1)首先打开safari,在上方菜单栏找到“safari”。(2)下拉找到系统“偏好设置”查看Flash player的所有插件是否安装,如果未安装需要安装好在进入下一步。(3)确认安装后继续在“偏好设置”中选择“安全性”,将选项“互联网插件”后面“允许插件”处勾选。(4)在点击设置将flash player中的“访问其他网络时”的该选项调整为“始终允许”即可正常使用flash player了。二、safari浏览器不兼容某些网页由于浏览器不兼容,导致网页无法打开或者异常崩溃,这个时候可以在设备中的safari浏览器中选择兼容模式,具体步骤如下:(1)打开safari浏览器,找到“偏好设置”。(2)在上方菜单栏找到“高级”选项,勾选在菜单中显示“开发”菜单。(3)在上方safari工具栏中找到“开发”选项。(4)下拉菜单找到“用户代理”选项选择兼容模式。以上就是关于移动端以及PC端通过safari浏览器打不开网页的一些处理办法,希望能对您有用,如果还有其他方法欢迎指出并探讨!

我要回帖

更多关于 浏览器打开新标签但是出现新窗口 的文章

 

随机推荐