pgadmin的导出图实现

PostgreSQL18的pgadmin中有一个ERDTool.jsx有1132行,这个体量理论上说非常庞大,但做过现实工程的都知道,其实只能算重组件中的mini尺寸了。pgadmin功能并不算有多丰富,怎么还是做成这样呢,当然不是维护团队不会拆分,毕竟还是做了199个jsx的。

首先映入眼帘的是registerEvents对19个EventBus的监听,这东西让人倒吸一口凉气,其中最醒目的莫过于this.eventBus.registerListener(ERD_EVENTS.DOWNLOAD_IMAGE, this.onImageClick),名字就不对劲,实现能如何呢?

这种百行级函数,存在合理性且不论,无论如何它都不应该叫xxClick了,毕竟谁敢相信它所有的代码都是为了完成一个导出png功能?

当然只笼统的说它完成了「一个功能」,那也是委屈它了,这函数实质上究竟做了什么?

状态管理: setLoading。

DOM 劫持: 直接操作样式和类名。

复杂的几何计算: 处理包围盒(Bounding Box)。

IO 操作: 生成图片并触发下载。

异常处理: 恢复状态弹出 notifier 警告。

每一项都是焦点,如果换成Java,这段代码还能再套上10个trycatch膨胀到500行,当然如果换成Java必然能规矩许多,不至于如此粗糙。

当然这函数远不止违法单一原则那么简单,几何计算中 margin = 10 和屏幕坐标转换逻辑非常硬核且粗糙,几乎宣判了这块UI已经不可更改了,同时否定了缩放/偏移变化,非常容易出 off-by-one 错误,已经消耗极大了,不想做复杂只想简单实现也可以克隆DOM做一个离屏渲染,还不需要关心什么margin偏移。

toPng还是html-to-image的,这种场景用这个本身就如同儿戏,而且既然都做这么复杂了,哪怕直接再补上一套原生代码,手动绘制,全丢这函数里,不用任何库,这段代码也不会更丑了。

检测到图片到了浏览器 canvas 限制,就直接剪裁+警告,不做一个执行前popup确认和zoom,可以说有些不可理喻了,现实中这个警告几乎不可能弹出来,因为符合的这个逻辑时,其占用的原始内存将达到惊人的 4GB,做这种巨型 DOM 树时UI会进行密集的像素计算。而且计算是同步的,会直接锁死浏览器主线程!程序早已卡死,一行代码都别想执行了。

还有setTimeout为什么 1000ms?为什么不是 500 或 2000?这是典型的“等它渲染完”的 hack,因为修改 transform / width/height 后,浏览器需要时间重排/重绘,html2canvas才能捕获正确内容。用requestAnimationFrame 循环检查或MutationObserver/ResizeObserver来检测实际变化完成不好么?

最后还是回到名字上,一个函数如果叫“xx点击”,它就没有资格去负责“计算并导出32767像素的位图”。

patek-shs.fdcpx.net

patek-bjs.fdcpx.net

patek-shenzhen.fdcpx.net

patek-shenzhen.longinesshwx.com

patek-shs.biaoshouhou.cn

patek-bjs.biaoshouhou.cn

patek-shenzhen.biaoshouhou.cn

patek-gzs.biaoshouhou.cn

patek-shs.szwatchpg.cn

patek-shs.buchererweixiu.com

patek-shenzhen.buchererweixiu.com

patek-gzs.buchererweixiu.com

patek-shs.audemarsweixiu.com

patek-bjs.audemarsweixiu.com

patek-shenzhen.audemarsweixiu.com

patek-shenzhen.mosershwx.com

patek-shs.hidcwatch.com

patek-bjs.hidcwatch.com

patek-shenzhen.hidcwatch.com

patek-gzs.hidcwatch.com

patek-shs.kpkwatch.com

patek-shs.watchgz.cn

patek-shenzhen.watchgz.cn

patek-gzs.watchgz.cn

patek-shs.fjfsx.com

patek-bjs.fjfsx.com

patek-shenzhen.fjfsx.com

patek-shenzhen.tagheueru.cn

patek-shs.hntwx.cn

patek-bjs.hntwx.cn

patek-shenzhen.hntwx.cn

patek-gzs.hntwx.cn

patek-shs.ywbzn.com

patek-shs.aysza.cn

patek-shenzhen.aysza.cn

patek-gzs.aysza.cn

patek-shs.hx626.com

patek-bjs.hx626.com

patek-shenzhen.hx626.com

patek-shenzhen.ernestshwx.com

patek-shs.watchjwf.cn

patek-bjs.watchjwf.cn

patek-shenzhen.watchjwf.cn

patek-gzs.watchjwf.cn

patek-shs.watchrhc.cn

patek-shs.zzjshd.com

patek-shenzhen.zzjshd.com

patek-gzs.zzjshd.com

patek-shs.shjshdzb.com

patek-bjs.shjshdzb.com

不过综合来说,这东西整体上也算勉强还行了,毕竟它是一个最终节点组件,而且基本上不太可能被依赖,只是功能性问题,不像它旁边那个1560行有15个useEffect的ResultSet.jsx,那都不能叫组件了,那是试图给React塞一个子系统,等PostgreSQL20发布,估计就没人敢改它了。还有用1300行的FormInput.tsx管理着FormIcon、StyledGrid、FormInput、InputSQL、FormInputSQL等子组件的超级组件,这几乎是想做一套扩展UI库。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容