micro-app-源码解析4-数据通信篇-终篇
创始人
2024-03-12 20:52:59

沙箱篇官方讲解地址

https://github.com/micro-zoe/micro-app/issues/21

1. 带着问题进行阅读

在做框架的时候,没法避免的遇见父子通信和兄弟通信的问题,但是如何实现通信这是个每个框架需要解决的问题。

1.1 如何选择父子通信的方式

最好的方式应该是像普通元素一样,通过micro-app元素传递数据。但自定义元素无法支持对象类型的属性,只能传递字符串,例如 会转换为

所以选择通过改写原型链上setAttribute方法处理对象类型属性,对传递的数据进行拦截,加上发布订阅实现父子的通信。

// /src/index.js// 记录原生方法
const rawSetAttribute = Element.prototype.setAttribute// 重写setAttribute
Element.prototype.setAttribute = function setAttribute (key, value) {// 目标为micro-app标签且属性名称为data时进行处理if (/^micro-app/i.test(this.tagName) && key === 'data') {if (toString.call(value) === '[object Object]') {// 克隆一个新的对象const cloneValue = {}Object.getOwnPropertyNames(value).forEach((propertyKey) => {// 过滤vue框架注入的数据if (!(typeof propertyKey === 'string' && propertyKey.indexOf('__') === 0)) {cloneValue[propertyKey] = value[propertyKey]}})// 数据拦截后对子应用发送数据BaseAppData.setData(this.getAttribute('name'), cloneValue)}} else {rawSetAttribute.call(this, key, value)}
}

1.2 为什么选择发布订阅

微前端各个应用本身是独立运行的,通信系统不应该对应用侵入太深,所以我们采用发布订阅系统。

1.3 兄弟间如何通信

子应用要发给其他子应用的数据先发给基座,基座进行分发。

发布订阅系统很灵活,但太过于灵活可能会导致数据传输的混乱,必须定义一套清晰的数据流。所以我们要进行数据绑定,基座应用一次只能向指定的子应用发送数据,子应用只能发送数据到基座应用,至于子应用之间的数据通信则通过基座应用进行控制,这样数据流就会变得清晰

2.原理详解

2.1 父亲应用对子应用进行传值

2.1.1 组件的data 属性传值

因为元素不能传递对象,所以最终的结果还是走了发布订阅。通过修改原生的setAttribute方法,当改变属性的时候,进行获取值,然后将获取的值放入发布订阅当中。进行传递。
请添加图片描述

// /src/index.js// 记录原生方法
const rawSetAttribute = Element.prototype.setAttribute// 重写setAttribute
Element.prototype.setAttribute = function setAttribute (key, value) {// 目标为micro-app标签且属性名称为data时进行处理if (/^micro-app/i.test(this.tagName) && key === 'data') {if (toString.call(value) === '[object Object]') {// 克隆一个新的对象const cloneValue = {}Object.getOwnPropertyNames(value).forEach((propertyKey) => {// 过滤vue框架注入的数据if (!(typeof propertyKey === 'string' && propertyKey.indexOf('__') === 0)) {cloneValue[propertyKey] = value[propertyKey]}})// 发送数据BaseAppData.setData(this.getAttribute('name'), cloneValue)}} else {rawSetAttribute.call(this, key, value)}
}

2.1.2 发布订阅传值

发布订阅功能的代码实现

// /src/data.js// 基座应用的数据通信方法集合
export class EventCenterForBaseApp {/*** 向指定子应用发送数据* @param appName 子应用名称* @param data 对象数据*/setData (appName, data) {eventCenter.dispatch(formatEventName(appName, true), data)}/*** 清空某个应用的监听函数* @param appName 子应用名称*/clearDataListener (appName) {eventCenter.off(formatEventName(appName, false))}
}

2.2 子应用对父亲应用进行传值

子应用对父亲的传值,通过标签本身的属性[data],通过datachange方法来进行传值的

核心代码

    const app = appInstanceMap.get(this.appName)if (app?.container) {// 子应用以自定义事件的形式发送数据const event = new CustomEvent('datachange', {detail: {data,}})app.container.dispatchEvent(event)}

2.3 父子应用传值的基本实现代码


// /src/data.js// 基座应用的数据通信方法集合
export class EventCenterForBaseApp {/*** 向指定子应用发送数据* @param appName 子应用名称* @param data 对象数据*/setData (appName, data) {eventCenter.dispatch(formatEventName(appName, true), data)}/*** 清空某个应用的监听函数* @param appName 子应用名称*/clearDataListener (appName) {eventCenter.off(formatEventName(appName, false))}
}// 子应用的数据通信方法集合
export class EventCenterForMicroApp {constructor (appName) {this.appName = appName}/*** 监听基座应用发送的数据* @param cb 绑定函数*/addDataListener (cb) {eventCenter.on(formatEventName(this.appName, true), cb)}/*** 解除监听函数* @param cb 绑定函数*/removeDataListener (cb) {if (typeof cb === 'function') {eventCenter.off(formatEventName(this.appName, true), cb)}}/*** 向基座应用发送数据* @param data 对象数据*/dispatch (data) {const app = appInstanceMap.get(this.appName)if (app?.container) {// 子应用以自定义事件的形式发送数据const event = new CustomEvent('datachange', {detail: {data,}})app.container.dispatchEvent(event)}}/*** 清空当前子应用绑定的所有监听函数*/clearDataListener () {eventCenter.off(formatEventName(this.appName, true))}
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...