为什么689款开源macOS应用值得你拥有?[特殊字符]
2026/9/3 8:39:41
应用场景:
实现场景:
利用同域下 LocalStorage 共享策略。
存在问题:
使用:
storage事件。e.newValue变化即可得知当前的传送的消息。removeItem时,e.newValue会变为 null。e.url判断消息是否为自己发出,避免重复处理,或者监听消息来源。// A 页面window.addEventListener('storage',(e)=>{console.log(e.key)// keyconsole.log(e.oldValue)// 旧值console.log(e.newValue)// 新值,即设置的值console.log(e.storageArea)// 被操作的 storage 对象console.log(e.url)// 文档改变的对象地址来源})// B 页面window.LocalStorage.setItem('xx','xxx')window.LocalStorage.removeItem('xxx','xxx')基于共享线程来完成通信,是独立于主线程的后台共享线程。
SharedWorker 本身承载业务共享逻辑,底层通信手段基于MessagePort实现。
port通信降低主线程和 Shared Worker 的耦合度。SecurityError:不能正常启动 Shraed Worker。NetworkError:Shared Worker 不是application/json格式。SyntaxError:URL 无法解析。存在问题:
chrome://inspect#workers界面查看调试信息。使用:
主线程:
shareWorker.port.postMessage向所有连接的页面发送消息。shareWorker.port.onmessage接收发来的消息。// 页面内(主线程)constshareWorker=newShareWorker('share-worker.js')shareWorker.port.onmessage=(e)=>{const{type,data}=e.dataif(type==='BROADCAST'){// 处理逻辑}}// 处理连接错误worker.port.onerror=function(error){console.error("Shared Worker 错误:",error);};// 显示激活shareWorker.port.start()functionsendMessage(){shareWorker.port.postMessage({type:'MESSAGE',data:{...}})}functiondisconnect(){shareWorker.port.postMessage({type:'DISCONNECT'})shareWorker.port.close()}shared worker文件:
self.onconnect监听连接事件,只要完成初始化就会触发。connections存储端口,支持 O(1) 操作消耗。port.onmessage监听任一主线程发来的消息,遍历connections广播消息。port.close关闭端口并清除端口在connections中的缓存,一定要清除连接,避免出现缓存端口导致广播无效端口的情况出现。port.start用于触发端口激活,调用不会触发什么内容,但是部分浏览器不调用可能会阻塞消息发送。// share-worker.js (share Worker线程)// 通过 connections 管理端口constconnections=newSet();// 消息广播functionbroadcast(){connections.forEach(p=>{// 排除自身if(p!==port){p.postMessage({type:'BROADCAST',data:`${data}`});}});}functiondisconnect(port){connections.delete(port);port.close();// 关闭端口}self.onconnect=(e)=>{// 1. 读取端口:自动去重constport=e.ports[0];connections.add(port);// 2. 监听消息port.onmessage=(e)=>{const{type,data}=e.data;switch(type){case'MESSAGE':console.log('收到主线程消息:',data);// 广播给所有连接的主线程broadcast(data,port)break;case'DISCONNECT':disconnect(port)break;}};// 3. 监听端口错误/关闭,自动清理无效端口port.onerror=(err)=>{console.log('端口错误:',err);connections.delete(port);};// 显示激活端口(部分浏览器需显式调用)port.start();};支持同源下跨标签页通信方案,适用于广播消息方案。
存在问题:
使用:
new BroadcastChannel(channelName)创建频道。message来监听广播消息。channel.postMessage()发送消息。constbroadcastChannel=newBroadcastChannel("channel");// 接收其他同频道的广播消息broadcastChannel.addEventListener("message",(e)=>{const{type,data}=e.data});// 为同频道广播消息broadcastChannle.postMessage({type:'message',data})当使用window.open()打开窗口,可以通过父子窗口执行通信。
存在问题:
使用:
window.open打开子窗口,同时保留子窗口的引用。window.name区分子窗口,便于后续跨子窗口通信。window的message事件实现通信 。child.postMessage()发送消息,子窗口通过window.opener.postMessage()回复消息,如果要跨域,可以通过 postMessage 第二参数指定目标源,*代表向所有源发送消息。// 父窗口constchild=window.open('/some-page')// 给子窗口定义唯一id,便于通信child.name='win_'+id()window.addEventlistener('message',()=>{// 监听子窗口传递的消息})// 在子窗口 /some-page 页面// 发送数据到父窗口window.opener.postMessage({type:'message',name:window.name,data})window.addEventlistener('message',()=>{// 监听父窗口传递的消息})通过 websocket ,以服务端做中转,实现跨域通信方案。
存在问题:
这个方案还是比较常用在 iframe 跨域通信机制中,仅记录。
MessageChannel 本质也是依赖 MessagePort 来实现的通信机制,本质和 SharedWorker 一样。
如果实现跨标签页通讯,需要有中间人且支持结构化克隆算法来协助传递 port 端口信息。