业务背景与挑战
业务组件需要高度绑定业务场景,为独立的场景单独设计。一般不会出现跨平台业务组件高度保持一致的需求,各平台保持数据一致性即可。可当客户提出组件多端保持一致的需求,而老板也觉得这样合理时,研发就要为此努力找到一个合理的解决方案,同时去兼容各端框架。
问题盘点
ECRP业务线多平台有多个高度复用的业务组件如:选择员工组件、选择店铺组件、选择区域、选择企微、选择商品等。各端业务线在不同的产品、UI规范下设计了不同的交互样式。SAAS客户在云平台操作各个业务线的产品发现使用中的问题:
-
多平台重复开发:选择店铺/员工/区域等核心业务组件在8+平台独立实现
-
体验割裂问题:相同功能组件存在5+种交互变体,用户跨平台操作需反复适应
-
数据一致性风险:各平台接口实现差异导致数据存在误差
技术方案
基于客户的真实需求我们需要对ECRP业务线各平台业务组件做归纳整理,同时需要给出解决方案。在梳理各平台公用业务组件的时候发现的问题如下:
- 业务组件的开发框架不一致(Vue、React)
- 业务组件在各产品的使用场景不一致,数据处理逻辑不一样,使用公共组件会不满足原始场景的问题
- 组件开发要考虑组件替换成本,毕竟全链路替换组件会带来不确定性
针对客户反馈的问题来拆解跨平台业务组件目标:
-
实现UI层100%一致性
-
保证数据源统一性(数据统一开源开放平台)
-
兼容Vue/React双技术栈
方案对比
| 方案 | 开发成本 | 维护成本 | 性能损耗 | 跨框架支持 |
|---|---|---|---|---|
| Web Components | 高 | 低 | 低 | 优 |
| 微前端 | 中 | 中 | 中 | 良 |
| React组件 + iframe | 低 | 低 | 中 | 优 |
微前端内嵌可以实现跨框架的接入,接入方式也相对简单。但这样开发业务组件会带来的问题是:需要有独立的团队一直维护业务组件,同时组件开发团队需要一直堆积不同平台的需求使得开发维护的周期变长。综合考虑之后我们给出的实现方案如下:
-
前端实现:React开发组件 + (Vue)iframe内嵌的调用(组件开发者保证业务组件的高度一致、使用场景高度可配)
-
后端:SDK对接,数据统一来源云平台保持数据一致性,减少重复开发成本。数据接口SDK支持各业务线后端开发者根据实际场景覆盖重写
实现方案
分层架构设计
┌───────────────┐
│ 业务应用层 │
│ (Vue/React) │
└──────┬────────┘
│ 事件通信
┌──────▼────────┐
│ 组件容器层 │
│ (React Core) │
└──────┬────────┘
│ SDK调用
┌──────▼────────┐
│ 数据服务层 │
│ (统一API网关) │
└───────────────┘
业务组件:@lib/pro-shop-select
React集成方案
apiRequest为各端独立的接口服务,服务来源有后端的SDK。满足大场景的需求同时支持各端独立覆盖。
import ProShopSelect from '@lib/pro-shop-select'
//业务组件
<ProShopSelect
placeholder="请选择店铺"
apiRequest={apiRequest}
options={{
}}
onOk={(res:any) => {
}}
/>
Vue集成方案
背景:Vue框架实现的页面都是作为子页面内嵌在React框架内部,因此可以通过消息监听的方式唤起组件。
- React使用iframe挂载业务组件
const Index: React.FC = () => {
// 是否打开组件
const [showShopSelect, setShowShopSelect] = useState(false);
const handleMessage = (e) => {
// 1.接受Vue页面发送的数据
console.log('handleMessage: ', 2)
// 2.打开业务组件
setShowShopSelect(true);
}
useMount(() => {
window.addEventListener('message', handleMessage)
});
return(
<>
{renderHtml()}
{
showShopSelect &&
<SelectShop
visible={showShopSelect}
onOk={(res) => {
document.getElementById('myiframe').contentWindow.postMessage({
type: ''
params: {}
}, '*')
// 关闭弹窗
setShowShopSelect(false)
}}
onCancel={() => {
// 点击取消按钮
// 关闭弹窗
setShowShopSelect(false)
}}
/>
}</>
)
};
export default Index;
- Vue调用选择店铺组件
export default {
created: function () {
window.addEventListener('message', (e) => {
// 监听消息,处理返回的数据
}, false)
},
// 点击打开业务组件
selectShopTagOpen () {
window.parent.postMessage({
type: '',
params: {}
}, '*')
},
}
效果与收益
| 指标 | 改造前 | 改造后 | 提升率 |
|---|---|---|---|
| 组件维护成本 | 8人日/月 | 2人日/月 | 75%↓ |
| 数据一致性 | 70% | 95% | 25%↑ |
经验总结
该方案已在ECRP业务线8个平台稳定运行。
- 渐进式改造策略
采用"分业务线逐步替换+AB测试"方案,保障业务连续性,降低全量替换风险 - 跨平台系统赋能
沉淀出跨平台设计体系,统一管理12种基础业务组件规范