前端技术中的常用通信方案

原生js通信 1. Event:
在发送方注册事件,并在接收方监听该事件来进行通信。发送方在适当的时机触发事件,接收方收到事件后执行相应的处理 event-example <body> <div id="wrap"> <button id="message">发送消息</button> <div id="receiver"></div> </div> <script> // 事件名称 const eventName = 'messageEvent'; // 发送方 const sendButton = document.getElementById('message'); // 接收方 const receiverElement = document.getElementById('receiver'); // 定义自定义事件 const customEvent = new Event(eventName); // 定义事件派发函数 function dispatchCustomEvent(e) { receiverElement.dispatchEvent(customEvent); } // 在发送按钮点击时调用事件派发函数 sendButton.addEventListener('click', dispatchCustomEvent); // 监听自定义事件 receiverElement.addEventListener(eventName, function(event) { // 收到事件后执行相应处理 console.log('接收到事件',event.type); }); </script> </body> 2.iframe
父页面监听iframe消息:
window.addEventListener('message', receiveMessageIframePage, false);
父页面发送给iframe页面的消息:
iframe.contentWindow.postMessage({ type: 'boundFileKeys', data: "消息内容体" }, '*');
iframe页面监听父页面发过来的消息:
window.addEventListener('message', onMessage, false);
iframe页面给父页面发送消息
window.parent.postMessage({ type: 'check', data: ["自定义需要发送的数据"] }, '*');
3.标签通信–频道 BroadcastChannel 接口代理了一个命名频道,可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件,消息可以广播到所有监听了该频道的 BroadcastChannel 对象 channel1 channel2 function BroadChannel(cb){ // 获取频道 this.get = function(channelname){ return this.channelMap.get(channelname) } // 获取默认频道名称 this.getDefaultName = function(){ return 'broad-channel-' + (this.channelMap.size + 1) } // 获取所有频道数 this.getLength = function(){ return this.channelMap.size } // 创建频道 this.create = function(channelname){ const self = this const name = channelname || self.getDefaultName() const channel = new BroadcastChannel(name) channel.onmessage = function(ev){ const message = { data: ev.data, name, time: Date.now() } cb && cb(message) } channel.onmessageerror = function(ev){ console.error(ev.data); } self.channelMap.set(name,channel) self.channelLength = self.getLength() return channel } // 开通频道 this.open = function (channelname){ const channel = this.get(channelname) return channel || this.create(channelname) } // 关闭频道 this.close = function(channelname){ const channel = this.get(channelname) if( channel ){ channel.close() } } // 删除频道 this.delete = function(channelname){ this.close(channelname) this.channelMap.delete(channelname) this.channelLength = this.getLength() } // 判断是否存在相同频道 this.has = function(channelname){ return this.channelMap.has(channelname) } // 发送消息 this.postMessage = function(channelname, data){ const channel = this.get(channelname) if( channel ){ try { // 正常 channel.postMessage(data) }catch (e) { // 频道已关闭,重新创建频道 this.delete(channelname) this.open(channelname) this.postMessage(channelname, data) } }else{ console.warn('【channel:'+channelname+'】: channel is not defined, you should first execute open method'); } } // 初始化 this.reset = function (){ // 频道名称集合 this.channelMap = new Map() this.channelLength = this.getLength() } this.reset() } const channel = new BroadChannel((data)=>{ console.log(data); }) channel.open('test').postMessage('test',111) channel.open('test2').postMessage('test2',222) console.log(channel); 4. ShareWorker SharedWorker是HTML5提供的一种Web Worker类型,它允许多个浏览器上下文(如多个窗口、标签页或框架)共享相同的Worker实例。与普通的Worker不同,SharedWorker可以跨浏览器上下文进行通信和共享数据 worker1 worker2 5.本地缓存 LocalStorage和SessionStorage LocalStorage和SessionStorage是浏览器提供的本地存储方案。它们可以在浏览器端存储和读取数据,并在同一域名下的不同页面间进行数据共享。LocalStorage和SessionStorage适用于在同一浏览器中的不同页面之间进行数据传递的需求 6. MessageChannel Channel Messaging API 的 MessageChannel 接口允许我们创建一个新的消息通道,并通过它的两个 MessagePort 属性发送数据 消息频道 事件总线 事件总线是一种在应用程序中实现组件间通信的机制。它允许组件之间通过订阅和发布事件来进行信息传递,无论这些组件是父子组件、兄弟组件或跨越组件树的。 事件总线的实现可以是一个全局的事件管理器或服务,也可以是一个专门为事件通信而创建的组件 方式1: import mitt from 'mitt' const EventBus = mitt(); 方式2 const EventBus = new Vue() 事件总线方法: EventBus.on("on-preview") EventBus.emit("on-preview", '图片地址') EventBus.off("on-preview") 7.交互通信 WebViewJavascriptBridge是一个用于在WebView与JavaScript之间进行双向通信的桥接库。它允许原生应用程序的WebView与嵌入的JavaScript通过桥接对象进行交互,实现数据传输和方法调用 js代码: /*这段代码是固定的,必须要放到js中*/ function setupWebViewJavascriptBridge(callback) { //判断机型 let u = navigator.userAgent; if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } //判断是否是ios if (/(iPhone|iPad|iPod|iOS|Mac OS)/i.test(u)) { if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; let WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe); }, 0); } else { document.addEventListener( 'WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false ); } } let Bridge = {}; Bridge.install = function (Vue, options) { Vue.prototype.$bridge = {}; /*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/ setupWebViewJavascriptBridge(function(bridge) { // 普通环境 - 生命全局变量 //初始化 //判断机型 let u = navigator.userAgent; if (!/(iPhone|iPad|iPod|iOS|Mac OS)/i.test(u)) { bridge.init(function(message, responseCallback) { let data = { 'Javascript Responds': 'Wee!' }; alert("jasdashjd"); responseCallback(data); }); } Vue.prototype.$bridge = bridge; }); // // setupWebViewJavascriptBridge(function (bridge) { // Vue.prototype.$bridge = bridge; // }) } export default Bridge; 8.安卓端代码: // 创建WebViewJavascriptBridge实例 WebViewJavascriptBridge bridge = new WebViewJavascriptBridge(context, webView, new BridgeHandler() { @Override public void handler(String data, CallBackFunction responseCallback) { // 处理JavaScript发送的消息 // ... // 发送响应给JavaScript responseCallback.onCallBack("Android response"); } }); // 注册一个Native Handler用于处理JavaScript请求 bridge.registerHandler("jsHandler", new BridgeHandler() { @Override public void handler(String data, CallBackFunction responseCallback) { // 处理JavaScript请求 // ... // 发送响应给JavaScript responseCallback.onCallBack("Android response"); } }); // 发送消息给JavaScript bridge.callHandler("nativeHandler", "Android message", new CallBackFunction() { @Override public void onCallBack(String responseData) { // 处理JavaScript响应 // ... } }); 9.ios端代码: // 导入WebViewJavascriptBridge头文件 #import "WebViewJavascriptBridge.h" // 创建一个WebViewJavascriptBridge实例 WebViewJavascriptBridge *bridge = [WebViewJavascriptBridge bridgeForWebView:webView]; // 注册一个处理Native请求的handler [bridge registerHandler:@"nativeHandler" handler:^(id data, WVJBResponseCallback responseCallback) { // 处理Native请求,如获取设备信息等 // ... // 回调JavaScript responseCallback(@"Native response"); }]; // 发送消息给JavaScript [bridge callHandler:@"jsHandler" data:@"Native message" responseCallback:^(id responseData) { // 处理JavaScript响应 // ... }]; 10.其他通信:
AJAX是一种通过在后台与服务器进行数据交换的技术。通过在页面上使用JavaScript,可以异步地发送HTTP请求,获取数据并更新页面内容,实现与服务器的数据交互
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许在客户端和服务器之间实时传输数据,同时支持服务器向客户端主动推送数据。WebSocket能够提供实时性和双向通信的能力,非常适合实时应用程序、即时通讯以及在线游戏等场景
Server-Sent Events是一种基于HTTP的服务器向客户端推送事件的技术。与WebSocket不同,SSE是一种单向通信机制,服务器可以向客户端推送数据,但客户端不能主动向服务器发送请求。SSE适用于需要实时更新的应用场景,如实时新闻、股票行情等
WebRTC(Web Real-Time Communication)是一种支持浏览器之间进行实时通信的开放性标准。它提供了音视频通信、数据传输和P2P文件共享等功能。WebRTC可以在Web应用程序中实现实时语音、视频通话和文件传输,同时也可以用于游戏、即时通讯和远程协作等场景 以及其他通信方式
注意 js开发中,通信问题一般都与浏览器安全协议有着密切的关系,也就是我们常说的跨域问题,面对不同的场景,可以选择不同的通信方式 使用Web API实现相关通信的方案时,需要考虑浏览器兼容性,一般主流浏览器都兼容,像IE或低版本浏览器会有兼容性问题
具体可以在MDN或者Can I Use网站查看
tiryLi

浙公网安备 33010602011771号