前端多系统集成通信

2018-04-20  本文已影响0人  Weastsea

1:目标

集成多个相互独立的系统展示在一个页面上,多个系统可以相互进行数据通信。

2:应用场景

假设页面内嵌两个系统,就是一个父系统集成2个子系统

一般会存在3种信息传递场景:
1: 父——>子 由父系统把消息传递到子系统

2:子1——>父——>子2🈶子1把消息传递给子2,但是需要父系统作为代理中转

3:子——> 父 由子系统把消息传递给父系统

3:依赖的主要技术——HTML5跨文档消息传递

跨文档消息传送(cross-document messaging),有时候简称为 XDM,指的是在来自不同域的页面间 传递消息。例如,www.wrox.com 域中的页面与位于一个内嵌框架中的 p2p.wrox.com 域中的页面通信。 在 XDM 机制出现之前,要稳妥地实现这种通信需要花很多工夫。XDM 把这种机制规范化,让我们能 既稳妥又简单地实现跨文档通信。——JavaScript高级程序设计

在此不再详细赘述此技术,可通过相关书籍(推荐《JavaScript高级程序设计》)和博客自行学习。

4:设计思路以及细节处理

注意: 前端框架使用vue

4.1: 我们首先解决从父——>子

步骤:

  1. 首先在父系统中嵌入iframe,注册2个子系统
    http://localhost:8082http://localhost:8080是启动的两个前端应用,分别代表app1和app2。父系统是 http://localhost:8081
<iframe id='app1' src="http://localhost:8082" frameborder="0" width="550" height="800">
</iframe>
<iframe id='app2' src="http://localhost:8080" frameborder="0" width="550" height="800">
</iframe>

2: 父系统触发事件,例如click事件,通过id获取子系统的window,然后发送消息,例如触发的事件名为:postMessage

//封装方法
 postMessage () {
      let app1Window = window.document.getElementById('app1').contentWindow
      let app2Window = window.document.getElementById('app2').contentWindow
      let postMstData = {
        //{'data':''}}需要传递的数据, ip字符串:目标targetd的ip地址(一定要拼写正确)
        'app1Window': [app1Window, {'data': '我是APP1'}, 'http://localhost:8082'],
        'app2Window': [app2Window, {'data': '我是APP2'}, 'http://localhost:8080']
      }
      this.postMstHandler(postMstData)
    },
// 父系统进行广播
    postMstHandler (obj) {
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (obj[key][0].postMessage) {
            obj[key][0].postMessage(obj[key][1], obj[key][2])
          }
        }
      }
    }

3: 子系统接收数据
以app1为例:
在vue中,可以写在mounted钩子函数中;
在原生js中,可以写在window.onload = function () {}中,页面渲染的时候进行接收消息事件注册

 mounted () {
      let _this = this
      //  注册window的message事件来监听和接收消息
      window.addEventListener('message', function (event) {
        // event.origin: 表示来源地址,此处必须写父系统的域名
        if (event.origin === 'http://localhost:8081') {
          _this.postMst = event.data['data']
          // 处理数据逻辑
           ......
        }
      })
    }

页面展示效果:


4.2: 解决从子——>父

以app1为例
app1系统触发事件,例如click事件,直接获取parent对象(父系统window),通过parent发送消息,例如触发的事件名为:postMessage

 postMessage () {
        if (parent.postMessage) {
        // 此处域名写父系统的
          parent.postMessage({'data': '我是从app1发往父系统的字符串'}, 'http://localhost:8081')
        }
      },

然后需要在父系统里注册message事件,来监测从app1传来的消息

mounted () {
   var This = this
   window.addEventListener('message', function (event) {
     if (event.origin === 'http://localhost:8082') {
       //event.data为 {'app1': data, location: 'http://localhost:8080'}
       let keys = Object.getOwnPropertyNames(event.data)
       console.log(keys)
       if (keys.length === 2) {
         // 子 -> 父 -> 子
         let app = keys[0]
         let appWindow = window.document.getElementById(app).contentWindow
         let postMstData = {
           'appWindow': [appWindow, {'data': event.data[app]}, event.data.location]
         }
         console.log(postMstData)
         This.postMstHandler(postMstData)
       } else {
         // 子 -> 父
         This.postMst = event.data['data']
       }
     }
   })
 },

页面展示效果:


4.3: 解决从子——>父——>子

解决办法是需要通过父系统作为代理来进行传递数据,我们从app1 将数据通过父系统传递给app2
首先在app2触发消息传递

 postMessage () {
        // 此数据项,表明APP1 要向哪一个APP发送消息,以父模块作为代理
        let data = '我是从app1发往app2的字符串'
        if (parent.postMessage) {
          parent.postMessage({'app2': data, location: 'http://localhost:8080'}, 'http://localhost:8081')
      },

父系统接收数据,做转发的准备

 mounted () {
   var This = this
   window.addEventListener('message', function (event) {
     if (event.origin === 'http://localhost:8082') {
       // {'app1': data, location: 'http://localhost:8080'}
       let keys = Object.getOwnPropertyNames(event.data)
       console.log(keys)
       if (keys.length === 2) {
         // 子 -> 父 -> 子
         let app = keys[0]
         let appWindow = window.document.getElementById(app).contentWindow
         let postMstData = {
           'appWindow': [appWindow, {'data': event.data[app]}, event.data.location]
         }
         console.log(postMstData)
         This.postMstHandler(postMstData)
       } else {
         // 子 -> 父
         This.postMst = event.data['data']
       }
     }
   })
 },

app2注册message事件,来接收从app来的消息

 mounted () {
      let _this = this
      window.addEventListener('message', function (evnet) {
        console.log(event.origin)
        if(event.origin === 'http://localhost:8081') {
          _this.postMst= event.data['data']
        }
      })
    },

页面展示效果如下:


上一篇下一篇

猜你喜欢

热点阅读