辛宝的玄酒清谈!

A Solo Place.

辛宝Otto

Be a Happy Man

最近在学 Nuxt.js

速通-TinyVue 组件库如何同时支持 vue23 react solid

发布于2023-11-26

更新于2023-11-26

归类blogs

Tagpost速通

速通-TinyVue 组件库如何同时支持 vue23 react solid

参考《原来 TinyVue 组件库跨框架(vue2、vue3、react、solid)是这样实现的?

这篇文章介绍了跨框架组件库的必要性和操作实践。看标题挺感兴趣的,这里做个速通,原文引用我会标注,默认是自己的理解和思考。

背景

OpenTiny 是华为出的组件库,包含 TinyNG TinyVue TinyEngine 等内容。

统一输出一套组件库的能力、api ,能够在不同技术栈保持相通,可以增强用户使用信心,增加开发效率,跨技术栈实现相同 UI 表现。再者,给自己的组件库建立人设标签,挖掘潜在的用户。

当然难度肯定也是有的。需要去抽象逻辑,抹平不同方案的差异。

这是官方给的架构图。图画得不是特别好哈哈,文章写的也不够好,但是 Talk is cheap, show me the code ,给了 GitHub 仓库 demo。可以辅助理解。

文章提到了两个技术或者思路,抽象如下:

  • common 适配层
  • renderless 无渲染逻辑层

比如同样一个 tab 菜单或者 button 按钮,可以分成 UI 表现和逻辑两块,UI 表现可以归类到 common 适配层,有哪些输入输出可以归类到逻辑层。

技术实现

使用 pnpm + monorepo 实现组件库管理。

技术实现思路:

准备环境

创建 monorepo 环境

准备不同的 scripts,比如 vue3 vue2 react solid ,使用微前端无界实现管理

依赖处理

某些依赖需要区分 vue2 vue3 所以使用 pnpm.packageExtensions 进行区分,头一次见这种用法。

  • 文章举例如何同时兼容 react solid,首先是设定 react-button 和 solid-button
  • 还需要创建 packages/components/{platform}/common 文件夹。
  • 很有趣的文章提到了 ahooks 依赖的目的是提供 react 的响应式能力对标 vue 的响应式数据,哈哈哈还真看到了 https://ahooks.gitee.io/zh-CN/hooks/use-reactive

image.png

  • solid 本身就是 Signal 起家的,自带响应式
  • react 使用 ahooks 进行模拟响应式数据
  • 模拟 vue 的 emit
  • 模拟 vue 的 nextTick

文章进行举例,如何编写 react solid 的代码,依次实现 emit useNextTick useSetup,其中 useSetup 中返回 render 方法的内容。

代码忽略。

理解 renderless 逻辑

这部分代码可以区分成两部分:

  • 框架有关的入口函数
  • 框架无关的纯函数

文章写的不够清楚,读了几遍还是有些困惑,可能还得实际操作才理解。

举例 button 组件,在不同的平台需要实现 click 事件、需要实现 timer 重复点击禁用的事件。

比如 renderless 中 react/solid 如何编写,同需要实现 renderless 方法,返回 state 需要引用的 handleClick timer 等方法。因为这里是适配层,只关注定义通用的 state 和框架有关的方法。

index 中实现框架无关的逻辑。在这里实现 handleClicktimer 相关逻辑。

对于 button 来说:

  • react.js solid.js 去实现状态管理、实现 click timer 方法
  • 具体 click 和 timer 如何实现在 index.js 通过框架无关的方式去实现

大致理解的逻辑如何实现,接下来是 UI 表现,这里没有黑科技,也是自己去实现 render 方法,只不过 react/vue 都支持 jsx,逻辑相近。

说到最后,还是放了一个 demo 实例,这样就清楚多了 https://github.com/opentiny/cross-framework-component

image.png

举例 packages/components/react ,这是 react 组件库 demo 内容,可以看到 common/src/index.js 这个文件是用来模拟框架差异,定义 useSetup 的,在 solid vue2 vue3 里也有

再看 src/button/src/pc.jsx 这里是定义 button 组件 UI 表现的。

这两个文件定义了 UI 部分,那逻辑部分如何处理呢,看下图

image.png

renderless/src/button 内部是 button 组件的逻辑,通用的放入 index.js ,适配的放到 react.js 里。

继续举例子,vue 中如何定义 button 组件呢,在 vue/buttonvue/common 两处内容里定义。

image.png

刚才说到微前端,这是为了做 playground ,在一套页面中展示不同的框架展示效果。

image.png

这里对应 packages/home 目录,这里使用微前端 wujie 来完成不同页面的嵌入。

image.png

展望

这展示了一种组件设计的思路,抽象、抹平差异。

有机会做进一步的理解。