ifm: 一个多 iframe 的消息交互方案

公司项目中的 mono 项目架构,采用的是 iframe 方式来进行的,不过涉及多种类似的 app 消息通讯又没有特别好的方案
更新于: 2023-02-09 11:27:31
项目主页: https://github.com/afeiship/iframe-packages

安装

npm install -S @jswork/react-iframe-mate

用法

  • index.tsx
  • commands.tsx
<ReactIframeMate commands={commands} isCorsDomain debug={false}>
    <App />
</ReactIframeMate>
import { NavigateFunction } from 'react-router-dom';
import { NavigateOptions } from 'react-router';

type NavigatePayload = {
    path: string;
    options?: NavigateOptions;
    delta?: number;
};

export default {
    navigate: (payload: NavigatePayload, context: any) => {
        const { path, options, delta } = payload;
        const { navigate } = context;
        return delta ? navigate(delta) : navigate(path, options);
    },
};
<button onClick={(e) => {
  const msg = {
    command: 'navigate',
    payload: {
      delta: -1,
    },
  };
  ifm.post(msg);
}}>
	子调父:Back
</button>

场景

  • 2个 iframe 之间有消息通讯
  • 2个 iframe 有共用的 主域名
  • 子项目与主项目URL同步,状态需要保持

方法

方法用法备注
ifm.post
ifm.post({
    command: 'your_command',
    payload: {
        // args
    }
});
matewindow 发送消息
ifm.emit同上是 ifm.post 的别名
ifm.update 更新 context
ifm.on  

IFM 算法备选方案

目前的 ifm 缺点在于,URL比较长,而且,如果想在其中看到 id 等显而易见的参数都不可能找到。

const qs = require('qs')

var str = {
    "command": "navigate",
    "payload": {
        "path": "/cas-protein/P000_000_001",
        "options": {
            "replace": true
        },
        "referer": "knowledge-base"
    }
}

var v1 = qs.stringify(str);
var v2 = qs.parse(v1)

console.log(v1);
console.log('-----------------');
console.log(v2);
command=navigate&payload%5Bpath%5D=%2Fcas-protein%2FP000_000_001&payload%5Boptions%5D%5Breplace%5D=true&payload%5Breferer%5D=knowledge-base
-----------------
{
  command: 'navigate',
  payload: {
    path: '/cas-protein/P000_000_001',
    options: { replace: 'true' },
    referer: 'knowledge-base'
  }
}

备选方案2:  url-encode-decode

const { encode, decode } = require('url-encode-decode')

var str = {
    "command": "navigate",
    "payload": {
        "path": "/cas-protein/P000_000_001",
        "options": {
            "replace": true
        },
        "referer": "knowledge-base"
    }
}

var v1 = encode(JSON.stringify(str));
var v2 = decode(v1)

console.log(v1);
console.log('-----------------');
console.log(v2);
%7B%22command%22%3A%22navigate%22%2C%22payload%22%3A%7B%22path%22%3A%22%2Fcas-protein%2FP000_000_001%22%2C%22options%22%3A%7B%22replace%22%3Atrue%7D%2C%22referer%22%3A%22knowledge-base%22%7D%7D
-----------------
{"command":"navigate","payload":{"path":"/cas-protein/P000_000_001","options":{"replace":true},"referer":"knowledge-base"}}

参考