發(fā):從拼UI到說(shuō)UI的轉(zhuǎn)變與實(shí)戰(zhàn)指南)
1. 從“拼UI”到“說(shuō)UI”一個(gè)前端老手的真實(shí)轉(zhuǎn)變“自從有了 AI我就再也不想拼 UI 了”——這句話我第一次在團(tuán)隊(duì)群里看到時(shí)差點(diǎn)以為是哪個(gè)剛?cè)胄械男氯嗽诎l(fā)牢騷。結(jié)果點(diǎn)開(kāi)一看是組里干了八年的老前端。他以前是那種連一個(gè)像素的間距都要跟設(shè)計(jì)稿死磕的人現(xiàn)在居然說(shuō)不想拼 UI 了。我當(dāng)時(shí)的反應(yīng)是要么他瘋了要么工具真的變了。后來(lái)我自己試了一圈才明白這句話背后的真實(shí)含義。它不是“AI 能一鍵生成完美界面”這種營(yíng)銷(xiāo)話術(shù)而是工作流的重心發(fā)生了轉(zhuǎn)移以前我們花大量時(shí)間在“把設(shè)計(jì)稿翻譯成代碼”這件事上現(xiàn)在這件事的邊際成本被壓得很低真正值錢(qián)的部分變成了“描述清楚你要什么”和“判斷生成結(jié)果對(duì)不對(duì)”。這篇文章想聊的就是這套轉(zhuǎn)變到底是怎么發(fā)生的。我會(huì)從“拼 UI 為什么讓人痛苦”講起拆解 AI 介入 UI 生產(chǎn)的具體環(huán)節(jié)給出可以直接抄的提示詞模板和驗(yàn)證流程再聊聊那些我踩過(guò)的坑——比如生成出來(lái)的代碼看著能跑但布局一塌糊涂、組件復(fù)用率低到離譜、響應(yīng)式完全沒(méi)考慮等等。適合所有還在手寫(xiě) CSS、手調(diào) Flex 布局的前端、全棧、獨(dú)立開(kāi)發(fā)者以及想搞清楚“AI 到底能不能替代 UI 工作”的技術(shù)負(fù)責(zé)人。先說(shuō)結(jié)論AI 不能替代你對(duì)界面結(jié)構(gòu)的理解但它能把你從重復(fù)勞動(dòng)里撈出來(lái)。前提是你得知道怎么用它以及在哪里不能信它。2. 拼 UI 這件事到底哪里讓人崩潰2.1 重復(fù)勞動(dòng)的本質(zhì)設(shè)計(jì)稿到代碼的“翻譯損耗”很多人以為拼 UI 累是因?yàn)椤皩?xiě) CSS 麻煩”其實(shí)不是。真正累的是翻譯過(guò)程中的信息損耗。設(shè)計(jì)稿里一個(gè)卡片標(biāo)注了 padding 24px、圓角 12px、陰影 0 4px 12px rgba(0,0,0,0.08)你照著寫(xiě)寫(xiě)完發(fā)現(xiàn)跟設(shè)計(jì)稿還是不一樣。為什么因?yàn)樵O(shè)計(jì)稿是靜態(tài)的而界面是活的——文字長(zhǎng)度會(huì)變、屏幕寬度會(huì)變、內(nèi)容多少會(huì)變。我統(tǒng)計(jì)過(guò)自己以前做一個(gè)中等復(fù)雜度頁(yè)面的時(shí)間分配大概 30% 在寫(xiě)結(jié)構(gòu)40% 在調(diào)樣式細(xì)節(jié)20% 在處理響應(yīng)式和邊界情況10% 在跟設(shè)計(jì)對(duì)稿。也就是說(shuō)超過(guò)一半的時(shí)間花在了“對(duì)齊”上而不是“創(chuàng)造”上。這種對(duì)齊工作有個(gè)特點(diǎn)它必須做但做完之后沒(méi)有任何沉淀。下次換個(gè)項(xiàng)目同樣的卡片、同樣的按鈕你還得再來(lái)一遍。AI 介入之后變化最大的就是這 40% 的調(diào)樣式細(xì)節(jié)。你把設(shè)計(jì)意圖描述清楚它能把基礎(chǔ)樣式一次性鋪出來(lái)你只需要微調(diào)。這不是“省時(shí)間”那么簡(jiǎn)單而是把你的注意力從“怎么寫(xiě)”轉(zhuǎn)移到了“要什么”。2.2 組件化并沒(méi)有解決所有問(wèn)題有人會(huì)說(shuō)不是有組件庫(kù)嗎Ant Design、Element Plus、shadcn/ui拿來(lái)就用怎么會(huì)累這話對(duì)了一半。組件庫(kù)解決的是“標(biāo)準(zhǔn)組件”的問(wèn)題但真實(shí)項(xiàng)目里大量存在的是非標(biāo)準(zhǔn)組合。比如一個(gè)帶折疊動(dòng)畫(huà)的篩選面板、一個(gè)支持拖拽排序的標(biāo)簽列表、一個(gè)在移動(dòng)端要變成抽屜的側(cè)邊欄。這些組件庫(kù)不提供你得自己拼。而且組件庫(kù)用多了會(huì)有另一個(gè)問(wèn)題樣式覆蓋的復(fù)雜度指數(shù)上升。你為了改一個(gè)按鈕的圓角可能要寫(xiě)三層選擇器為了調(diào)整表格行高得翻半天文檔找對(duì)應(yīng)的 CSS 變量。這種“跟框架搏斗”的時(shí)間在 AI 輔助下能明顯壓縮——因?yàn)槟憧梢灾苯影研枨竺枋鼋o它讓它生成覆蓋樣式而不是自己去翻源碼。2.3 真正讓人不想拼的是“不可復(fù)用”我見(jiàn)過(guò)太多項(xiàng)目頁(yè)面寫(xiě)了上百個(gè)但組件復(fù)用率不到 20%。每個(gè)頁(yè)面都在重新造輪子只是輪子的顏色和尺寸略有不同。這不是開(kāi)發(fā)者懶而是在趕工期的時(shí)候抽象是最先被犧牲的。你明知道這兩個(gè)卡片可以合并成一個(gè)組件但合并要改 props、要處理差異、要測(cè)試不如復(fù)制一份改改快。AI 在這個(gè)環(huán)節(jié)的價(jià)值不是幫你寫(xiě)組件而是幫你識(shí)別哪些東西該被抽象。你把幾個(gè)相似的頁(yè)面結(jié)構(gòu)丟給它它能告訴你哪些部分是重復(fù)的、可以抽成公共組件。這個(gè)能力在以前需要經(jīng)驗(yàn)豐富的架構(gòu)師來(lái)做現(xiàn)在一個(gè)中級(jí)開(kāi)發(fā)者借助 AI 也能做到七八成。3. AI 介入 UI 生產(chǎn)的三個(gè)真實(shí)切入點(diǎn)3.1 從文字描述直接生成結(jié)構(gòu)代碼這是最直觀的用法。你不需要畫(huà)設(shè)計(jì)稿直接用自然語(yǔ)言描述界面讓 AI 生成 HTML/CSS 或 JSX/Tailwind 代碼。比如生成一個(gè)用戶(hù)信息卡片包含頭像圓形64px、姓名16px 加粗、職位14px 灰色、一行簡(jiǎn)介最多兩行超出省略號(hào)右下角有一個(gè)“關(guān)注”按鈕整體圓角 12px有輕微陰影。這種描述丟給現(xiàn)在的 AI基本能一次生成可用的代碼。但關(guān)鍵在于描述的顆粒度。我試過(guò)只寫(xiě)“生成一個(gè)用戶(hù)卡片”出來(lái)的東西完全不能用寫(xiě)到上面這個(gè)程度出來(lái)的代碼改兩行就能上。所以核心技能不是“會(huì)用 AI”而是能把界面拆解成可描述的屬性。這里有個(gè)我常用的模板你可以直接抄生成一個(gè) [組件類(lèi)型]要求如下 - 布局[flex/grid/block]主軸方向?qū)R方式 - 尺寸寬度 [固定/自適應(yīng)/百分比]高度 [固定/最小高度] - 間距內(nèi)邊距 [上下左右]外邊距 [上下左右] - 圓角[數(shù)值] - 陰影[描述或具體值] - 字體標(biāo)題 [字號(hào)/字重/顏色]正文 [字號(hào)/字重/顏色] - 交互[hover/active/focus 狀態(tài)變化] - 響應(yīng)式[斷點(diǎn)及對(duì)應(yīng)變化] - 技術(shù)棧[React/Vue/原生 CSS 方案]用這個(gè)模板生成結(jié)果的可用率能從 30% 提到 80% 以上。剩下的 20% 通常是響應(yīng)式和邊界情況需要手動(dòng)補(bǔ)。3.2 從截圖或設(shè)計(jì)稿反向生成代碼另一個(gè)高頻場(chǎng)景是設(shè)計(jì)給了 Figma 鏈接或者一張截圖你要把它變成代碼。以前的做法是量間距、取色值、手動(dòng)寫(xiě)。現(xiàn)在可以把截圖丟給支持視覺(jué)的 AI 模型讓它直接輸出代碼。實(shí)測(cè)下來(lái)這個(gè)方式的準(zhǔn)確率取決于截圖的清晰度和界面的復(fù)雜度。簡(jiǎn)單的卡片、表單、列表準(zhǔn)確率很高復(fù)雜的儀表盤(pán)、帶大量圖表的頁(yè)面AI 容易漏掉細(xì)節(jié)。我的做法是分塊處理把頁(yè)面拆成頭部、側(cè)邊欄、內(nèi)容區(qū)、底部一塊一塊生成最后拼起來(lái)。這樣比整頁(yè)生成準(zhǔn)確得多而且出錯(cuò)了容易定位。有個(gè)細(xì)節(jié)要注意AI 從截圖生成代碼時(shí)顏色和間距經(jīng)常是“近似值”。它可能把 #F5F5F5 寫(xiě)成 #F4F4F4把 24px 寫(xiě)成 20px。所以生成之后必須跟設(shè)計(jì)稿核對(duì)一遍關(guān)鍵數(shù)值。我一般會(huì)讓它把用到的顏色和間距單獨(dú)列出來(lái)方便對(duì)照。3.3 在已有代碼基礎(chǔ)上做增量修改這是我覺(jué)得最實(shí)用的場(chǎng)景也是“不想拼 UI”的核心原因。以前改一個(gè)樣式你要找到對(duì)應(yīng)的文件、定位到具體行、改完還要擔(dān)心影響別的地方?,F(xiàn)在可以直接把相關(guān)代碼貼給 AI用自然語(yǔ)言描述修改需求把這個(gè)卡片的陰影去掉圓角從 8px 改成 16px按鈕從右對(duì)齊改成居中移動(dòng)端下內(nèi)邊距從 16px 改成 12px。AI 會(huì)直接給你改好的代碼。你只需要 review 一遍確認(rèn)沒(méi)有誤傷其他樣式。這種方式特別適合迭代階段的微調(diào)效率提升非常明顯。但這里有個(gè)坑AI 可能會(huì)“順手”改掉你沒(méi)讓它改的東西。比如你讓它改圓角它可能把邊框顏色也調(diào)了。所以我的習(xí)慣是每次修改只提一個(gè)明確的需求改完確認(rèn)無(wú)誤再進(jìn)行下一個(gè)。批量提需求雖然快但出錯(cuò)后排查成本高。4. 提示詞寫(xiě)得好UI 代碼差不了4.1 結(jié)構(gòu)描述用“盒子思維”代替“視覺(jué)思維”很多人描述界面時(shí)習(xí)慣說(shuō)“左邊一個(gè)頭像右邊上面是名字下面是職位”這種描述對(duì)人沒(méi)問(wèn)題對(duì) AI 就容易產(chǎn)生歧義。更有效的方式是用盒模型的語(yǔ)言來(lái)描述外層容器flex 橫向排列align-items 居中g(shù)ap 12pxpadding 16px。 左側(cè)子元素固定 64x64圓角 50%。 右側(cè)子元素flex 縱向排列g(shù)ap 4pxflex: 1。 右側(cè)第一行文字“張三”16pxfont-weight 600。 右側(cè)第二行文字“前端工程師”14px顏色 #666。這種描述方式的好處是沒(méi)有歧義。AI 不需要猜“左邊”是多左、“右邊”是多右它只需要按照盒模型一層層搭就行。我剛開(kāi)始用 AI 生成 UI 時(shí)最大的問(wèn)題就是描述太“視覺(jué)化”導(dǎo)致生成結(jié)果跟預(yù)期差很遠(yuǎn)。改成盒模型描述之后準(zhǔn)確率大幅提升。4.2 樣式約束把設(shè)計(jì)系統(tǒng)“喂”給 AI如果你所在團(tuán)隊(duì)有設(shè)計(jì)系統(tǒng)比如主色 #1677FF、圓角統(tǒng)一 8px、間距用 4 的倍數(shù)一定要在提示詞里把這些約束寫(xiě)清楚。否則 AI 會(huì)自由發(fā)揮生成一堆“看起來(lái)還行但跟設(shè)計(jì)系統(tǒng)不搭”的樣式。我通常會(huì)在對(duì)話開(kāi)始時(shí)先給一段“系統(tǒng)提示”本項(xiàng)目使用以下設(shè)計(jì)規(guī)范 - 主色#1677FF輔助色#52C41A、#FAAD14、#FF4D4F - 圓角小 4px中 8px大 16px - 間距4px 的倍數(shù)常用 8/12/16/24/32 - 字體系統(tǒng)默認(rèn)字體棧標(biāo)題 16px/600正文 14px/400輔助 12px/400 - 陰影卡片 0 2px 8px rgba(0,0,0,0.08) - 技術(shù)棧React Tailwind CSS把這段放在對(duì)話最前面后續(xù)所有生成都會(huì)遵循這個(gè)規(guī)范。實(shí)測(cè)下來(lái)這樣生成的代碼幾乎不需要再調(diào)樣式直接就能用。4.3 交互狀態(tài)別漏了 hover、focus、disabled新手用 AI 生成 UI 時(shí)最容易漏的是交互狀態(tài)。你描述了一個(gè)按鈕AI 給你生成了默認(rèn)樣式但 hover 什么樣、點(diǎn)擊什么樣、禁用什么樣全沒(méi)寫(xiě)。結(jié)果就是界面“能看但不能用”。我的做法是在提示詞里顯式列出所有狀態(tài)按鈕組件 - 默認(rèn)背景 #1677FF文字白色圓角 8pxpadding 8px 16px - hover背景 #4096FF - active背景 #0958D9 - disabled背景 #F5F5F5文字 #BFBFBFcursor not-allowed - focus外發(fā)光 0 0 0 2px rgba(22,119,255,0.2)這樣生成出來(lái)的按鈕才是完整的。雖然多寫(xiě)幾行但省去了后面手動(dòng)補(bǔ)狀態(tài)的時(shí)間總體是劃算的。5. 生成之后驗(yàn)證與修正的完整鏈路5.1 先看結(jié)構(gòu)再看樣式AI 生成的代碼拿到手不要急著看樣式對(duì)不對(duì)。先看 DOM 結(jié)構(gòu)是否合理。我見(jiàn)過(guò)太多生成結(jié)果樣式看著沒(méi)問(wèn)題但結(jié)構(gòu)嵌套了七八層 div或者該用語(yǔ)義化標(biāo)簽的地方全用了 div。這種代碼短期能跑長(zhǎng)期維護(hù)是災(zāi)難。我的檢查順序是結(jié)構(gòu)層級(jí)是否扁平一般不超過(guò) 4 層是否使用了語(yǔ)義化標(biāo)簽header、nav、main、section、button 等類(lèi)名是否有意義不是 div1、div2 這種樣式是否內(nèi)聯(lián)內(nèi)聯(lián)樣式盡量少優(yōu)先用 class響應(yīng)式斷點(diǎn)是否合理這五步走完基本能過(guò)濾掉 80% 的“看著能用但實(shí)際不能維護(hù)”的代碼。5.2 用真實(shí)數(shù)據(jù)“壓”一遍AI 生成 UI 時(shí)默認(rèn)用的是“理想數(shù)據(jù)”——名字是兩三個(gè)字、簡(jiǎn)介是一句話、列表是三五條。但真實(shí)場(chǎng)景里名字可能有十幾個(gè)字、簡(jiǎn)介可能是一大段、列表可能有上百條。所以生成之后一定要用極端數(shù)據(jù)測(cè)一遍。我常用的測(cè)試數(shù)據(jù)超長(zhǎng)文本一段 200 字的中文看是否溢出、是否省略空數(shù)據(jù)列表為空、頭像加載失敗看是否有兜底超多數(shù)據(jù)列表 100 條看是否卡頓、是否需要虛擬滾動(dòng)窄屏320px 寬度下看布局是否錯(cuò)亂這一步能暴露大量 AI 生成時(shí)沒(méi)考慮到的邊界問(wèn)題。我遇到過(guò)生成的卡片在超長(zhǎng)文本下直接撐破容器也遇到過(guò)空列表時(shí)頁(yè)面一片空白沒(méi)有任何提示。這些問(wèn)題不測(cè)是發(fā)現(xiàn)不了的。5.3 組件抽取從“能用”到“好用”的關(guān)鍵一步AI 生成的代碼往往是“頁(yè)面級(jí)”的一個(gè)文件里堆了所有東西。直接上線也能跑但復(fù)用性很差。我的做法是生成之后手動(dòng)做一次組件抽取把重復(fù)出現(xiàn)的結(jié)構(gòu)抽成組件把可配置的部分抽成 props把狀態(tài)邏輯抽成 hooks 或 composables這一步 AI 也能幫忙。你可以把生成的兩個(gè)相似頁(yè)面貼給它問(wèn)“這兩個(gè)頁(yè)面有哪些部分可以抽成公共組件”它會(huì)給出建議。但最終的抽取決策還是要人來(lái)做因?yàn)?AI 不了解你的業(yè)務(wù)上下文。6. 那些 AI 生成 UI 時(shí)一定會(huì)踩的坑6.1 布局“看起來(lái)對(duì)但一測(cè)就崩”這是最高頻的問(wèn)題。AI 生成的布局在標(biāo)準(zhǔn)屏幕寬度下看著沒(méi)問(wèn)題一旦屏幕變窄或變寬立刻錯(cuò)亂。根本原因是AI 傾向于用固定寬度和絕對(duì)定位而不是彈性布局。我的應(yīng)對(duì)方式是在提示詞里強(qiáng)制要求所有布局必須使用 flex 或 grid禁止使用固定寬度除非是頭像、圖標(biāo)等確實(shí)需要固定的元素禁止使用絕對(duì)定位除非是遮罩、彈窗等確實(shí)需要脫離文檔流的場(chǎng)景。加上這條約束之后布局的健壯性明顯提升。6.2 顏色和間距的“近似值”陷阱前面提過(guò)AI 從截圖生成代碼時(shí)顏色和間距經(jīng)常是近似值。這個(gè)問(wèn)題在純文字描述時(shí)也會(huì)出現(xiàn)——你說(shuō)“淺灰色”它可能給你 #999也可能給你 #CCC。所以關(guān)鍵數(shù)值一定要顯式指定不要用“淺灰”“大一點(diǎn)”“稍微”這種模糊詞。我現(xiàn)在的習(xí)慣是所有顏色用十六進(jìn)制所有間距用像素值所有字號(hào)用具體數(shù)字。雖然寫(xiě)起來(lái)麻煩一點(diǎn)但省去了后面反復(fù)調(diào)整的時(shí)間。6.3 無(wú)障礙屬性幾乎從不主動(dòng)生成AI 生成 UI 時(shí)幾乎不會(huì)主動(dòng)加 aria-label、role、tabindex 這些無(wú)障礙屬性。如果你的項(xiàng)目有無(wú)障礙要求必須在提示詞里明確提出來(lái)所有交互元素必須包含適當(dāng)?shù)?aria 屬性按鈕需要 aria-label彈窗需要 roledialog 和 aria-modaltrue表單元素需要關(guān)聯(lián) label。不加這條生成出來(lái)的代碼在無(wú)障礙掃描工具下基本全是紅。6.4 響應(yīng)式斷點(diǎn)“一刀切”AI 默認(rèn)的響應(yīng)式策略往往是“小于 768px 就堆疊”但真實(shí)項(xiàng)目里斷點(diǎn)要根據(jù)內(nèi)容來(lái)定。一個(gè)三列布局可能在 1024px 就需要變兩列在 640px 變一列。所以斷點(diǎn)值也要在提示詞里說(shuō)清楚不要讓它自己猜。7. 把 AI 嵌進(jìn)日常工作流的幾種姿勢(shì)7.1 新頁(yè)面先生成骨架再填業(yè)務(wù)邏輯我現(xiàn)在做新頁(yè)面的流程是用文字描述頁(yè)面結(jié)構(gòu)讓 AI 生成靜態(tài)骨架HTML CSS手動(dòng)把骨架拆成組件接入真實(shí)數(shù)據(jù)和業(yè)務(wù)邏輯用極端數(shù)據(jù)測(cè)試修正邊界問(wèn)題這個(gè)流程比傳統(tǒng)方式快很多因?yàn)榈?1 步和第 2 步以前要花大半天現(xiàn)在半小時(shí)就能搞定。省下來(lái)的時(shí)間可以用在第 3 步和第 4 步把業(yè)務(wù)邏輯和邊界處理做得更扎實(shí)。7.2 老頁(yè)面改造讓 AI 先“讀懂”再改改造老頁(yè)面時(shí)我習(xí)慣先把相關(guān)代碼貼給 AI讓它總結(jié)這個(gè)頁(yè)面的結(jié)構(gòu)和樣式邏輯。等它“讀懂”之后再提具體的修改需求。這樣比直接讓它改要準(zhǔn)確得多因?yàn)樗辛松舷挛?。比如我?huì)先問(wèn)“這個(gè)頁(yè)面的布局結(jié)構(gòu)是什么用了哪些主要的 CSS 類(lèi)”等它回答完我再提“現(xiàn)在把卡片區(qū)域的間距從 16px 改成 24px其他不變。”這樣它就不會(huì)誤傷其他部分。7.3 設(shè)計(jì)稿走查用 AI 做第一輪比對(duì)設(shè)計(jì)稿和實(shí)現(xiàn)之間的差異以前靠人眼比對(duì)費(fèi)時(shí)費(fèi)力?,F(xiàn)在可以把設(shè)計(jì)稿截圖和實(shí)現(xiàn)截圖一起丟給 AI讓它列出差異點(diǎn)。雖然不能完全替代人工走查但能過(guò)濾掉大部分明顯的問(wèn)題比如間距不對(duì)、顏色偏差、圓角不一致等。我實(shí)測(cè)下來(lái)AI 走查能發(fā)現(xiàn) 70% 左右的視覺(jué)差異剩下的 30% 通常是需要結(jié)合交互才能發(fā)現(xiàn)的問(wèn)題。作為第一輪過(guò)濾效率提升很明顯。8. 關(guān)于“不想拼 UI”這件事我的真實(shí)體會(huì)用了大半年 AI 輔助 UI 開(kāi)發(fā)之后我確實(shí)“不想拼 UI”了——但不是因?yàn)?AI 能替代我而是因?yàn)槠?UI 這件事本身的價(jià)值變了。以前拼 UI 是核心技能現(xiàn)在它變成了一個(gè)“描述清楚就能自動(dòng)完成”的環(huán)節(jié)。真正值錢(qián)的能力變成了能不能把界面需求拆解清楚、能不能判斷生成結(jié)果的質(zhì)量、能不能在生成的基礎(chǔ)上做抽象和優(yōu)化。我現(xiàn)在的狀態(tài)是打開(kāi)編輯器的第一件事不再是寫(xiě)div而是想“這個(gè)界面該怎么描述”。描述清楚了代碼自然就出來(lái)了。描述不清楚生成一百遍也是白搭。所以如果你問(wèn)我 AI 到底能不能替代 UI 工作我的回答是它替代的是“翻譯”環(huán)節(jié)不是“設(shè)計(jì)”和“判斷”環(huán)節(jié)。而后者恰恰是區(qū)分普通開(kāi)發(fā)者和優(yōu)秀開(kāi)發(fā)者的地方。最后分享一個(gè)我最近常用的技巧每次生成完代碼不要急著用先讓 AI 自己 review 一遍問(wèn)它“這段代碼有哪些潛在問(wèn)題”。它經(jīng)常能發(fā)現(xiàn)自己剛才漏掉的東西比如沒(méi)處理空狀態(tài)、沒(méi)加 loading、某個(gè)地方用了固定寬度。這個(gè)“自檢”步驟花不了幾秒鐘但能省去后面很多調(diào)試時(shí)間。