参考《原来 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
- 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
中实现框架无关的逻辑。在这里实现 handleClick
和 timer
相关逻辑。
对于 button 来说:
react.js
solid.js
去实现状态管理、实现 click timer 方法- 具体 click 和 timer 如何实现在
index.js
通过框架无关的方式去实现
大致理解的逻辑如何实现,接下来是 UI 表现,这里没有黑科技,也是自己去实现 render 方法,只不过 react/vue 都支持 jsx,逻辑相近。
说到最后,还是放了一个 demo 实例,这样就清楚多了
https://github.com/opentiny/cross-framework-component
举例 packages/components/react
,这是 react 组件库 demo 内容,可以看到 common/src/index.js
这个文件是用来模拟框架差异,定义 useSetup
的,在 solid vue2 vue3 里也有
再看 src/button/src/pc.jsx
这里是定义 button 组件 UI 表现的。
这两个文件定义了 UI 部分,那逻辑部分如何处理呢,看下图
renderless/src/button
内部是 button 组件的逻辑,通用的放入 index.js
,适配的放到 react.js
里。
继续举例子,vue 中如何定义 button 组件呢,在 vue/button
和 vue/common
两处内容里定义。
刚才说到微前端,这是为了做 playground ,在一套页面中展示不同的框架展示效果。
这里对应 packages/home
目录,这里使用微前端 wujie 来完成不同页面的嵌入。
展望#
这展示了一种组件设计的思路,抽象、抹平差异。
有机会做进一步的理解。