PostgreSQL18的pgadmin中有一個ERDTool.jsx有1132行,這個體量理論上說非常龐大,但做過現(xiàn)實工程的都知道,其實只能算重組件中的mini尺寸了。pgadmin功能并不算有多豐富,怎么還是做成這樣呢,當然不是維護團隊不會拆分,畢竟還是做了199個jsx的。
首先映入眼簾的是registerEvents對19個EventBus的監(jiān)聽,這東西讓人倒吸一口涼氣,其中最醒目的莫過于this.eventBus.registerListener(ERD_EVENTS.DOWNLOAD_IMAGE, this.onImageClick),名字就不對勁,實現(xiàn)能如何呢?
這種百行級函數(shù),存在合理性且不論,無論如何它都不應該叫xxClick了,畢竟誰敢相信它所有的代碼都是為了完成一個導出png功能?
當然只籠統(tǒng)的說它完成了「一個功能」,那也是委屈它了,這函數(shù)實質(zhì)上究竟做了什么?
狀態(tài)管理: setLoading。
DOM 劫持: 直接操作樣式和類名。
復雜的幾何計算: 處理包圍盒(Bounding Box)。
IO 操作: 生成圖片并觸發(fā)下載。
異常處理: 恢復狀態(tài)彈出 notifier 警告。
每一項都是焦點,如果換成Java,這段代碼還能再套上10個trycatch膨脹到500行,當然如果換成Java必然能規(guī)矩許多,不至于如此粗糙。
當然這函數(shù)遠不止違法單一原則那么簡單,幾何計算中 margin = 10 和屏幕坐標轉(zhuǎn)換邏輯非常硬核且粗糙,幾乎宣判了這塊UI已經(jīng)不可更改了,同時否定了縮放/偏移變化,非常容易出 off-by-one 錯誤,已經(jīng)消耗極大了,不想做復雜只想簡單實現(xiàn)也可以克隆DOM做一個離屏渲染,還不需要關(guān)心什么margin偏移。
toPng還是html-to-image的,這種場景用這個本身就如同兒戲,而且既然都做這么復雜了,哪怕直接再補上一套原生代碼,手動繪制,全丟這函數(shù)里,不用任何庫,這段代碼也不會更丑了。
檢測到圖片到了瀏覽器 canvas 限制,就直接剪裁+警告,不做一個執(zhí)行前popup確認和zoom,可以說有些不可理喻了,現(xiàn)實中這個警告幾乎不可能彈出來,因為符合的這個邏輯時,其占用的原始內(nèi)存將達到驚人的 4GB,做這種巨型 DOM 樹時UI會進行密集的像素計算。而且計算是同步的,會直接鎖死瀏覽器主線程!程序早已卡死,一行代碼都別想執(zhí)行了。
還有setTimeout為什么 1000ms?為什么不是 500 或 2000?這是典型的“等它渲染完”的 hack,因為修改 transform / width/height 后,瀏覽器需要時間重排/重繪,html2canvas才能捕獲正確內(nèi)容。用requestAnimationFrame 循環(huán)檢查或MutationObserver/ResizeObserver來檢測實際變化完成不好么?
最后還是回到名字上,一個函數(shù)如果叫“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
不過綜合來說,這東西整體上也算勉強還行了,畢竟它是一個最終節(jié)點組件,而且基本上不太可能被依賴,只是功能性問題,不像它旁邊那個1560行有15個useEffect的ResultSet.jsx,那都不能叫組件了,那是試圖給React塞一個子系統(tǒng),等PostgreSQL20發(fā)布,估計就沒人敢改它了。還有用1300行的FormInput.tsx管理著FormIcon、StyledGrid、FormInput、InputSQL、FormInputSQL等子組件的超級組件,這幾乎是想做一套擴展UI庫。