證清單)
1. 移動端適配為什么總在真機(jī)上翻車做 Vue 移動端項(xiàng)目最容易踩的坑不是業(yè)務(wù)邏輯而是適配。你在 Chrome 的 iPhone 模擬器里調(diào)得好好的換到真機(jī)上一看字體忽大忽小、按鈕被擠到屏幕外、1px 邊框在某些機(jī)型上粗得像 3px。這類問題的根源通常只有一個——你用的是固定 px而移動端設(shè)備的邏輯像素寬度從 320 到 428 不等甚至折疊屏展開后更寬。lib-flexible 解決的就是這件事。它的核心思路是根據(jù)設(shè)備寬度動態(tài)設(shè)置根元素html的font-size然后所有尺寸用 rem 表示。設(shè)計稿通常是 750px 寬對應(yīng) iPhone 6/7/8 的 2 倍圖lib-flexible 會把屏幕分成 10 份每份就是 1rem。750 的設(shè)計稿上1rem 75px到了 375 邏輯寬度的手機(jī)上1rem 37.5px。元素寫width: 2rem在 750 稿上就是 150px在 375 屏上自動變成 75px比例完全一致。這套方案適合誰適合用 Vue CLI 搭建的移動端 H5 項(xiàng)目尤其是需要一套代碼適配多種屏幕寬度的場景。它不依賴任何后端服務(wù)純前端計算接入成本低。下面我把從安裝到真機(jī)驗(yàn)證的完整路徑拆開講每一步都給可復(fù)制的配置。2. 接入前的環(huán)境確認(rèn)與 TaoToken 前置準(zhǔn)備在動手改配置之前先確認(rèn)你的項(xiàng)目環(huán)境。lib-flexible 對 Vue 2 和 Vue 3 都兼容但配置方式略有差異。Vue CLI 項(xiàng)目看vue.config.js或build/utils.jsVite 項(xiàng)目則走postcss.config.js。我下面以 Vue CLI 為主Vite 的差異會單獨(dú)標(biāo)注。另外如果你在開發(fā)過程中需要調(diào)用大模型接口做輔助比如讓模型幫你檢查 rem 換算、生成適配代碼片段可以先把 API Key 準(zhǔn)備好。TaoToken 的接入文檔在 https://taotoken.net/apiKey 在控制臺的 API Keys 頁面生成https://taotoken.net/console/api-keys。拿到 Key 之后模型對話入口在 https://taotoken.net/models編碼場景可以用 Coding Planhttps://taotoken.net/coding-plan。這部分不是適配的必需步驟但如果你想讓模型幫你批量轉(zhuǎn)換設(shè)計稿尺寸提前配好會省事?;氐竭m配本身。你需要確認(rèn)三件事項(xiàng)目用的是 Vue CLI 還是 Vite、有沒有裝 PostCSS、設(shè)計稿寬度是多少。設(shè)計稿寬度決定了 rem 基準(zhǔn)值750 稿對應(yīng) 75375 稿對應(yīng) 37.5。這個值后面配置 postcss-pxtorem 時要用。3. 可復(fù)制的 main.js 與 postcss 配置3.1 安裝依賴打開終端在項(xiàng)目根目錄執(zhí)行npm install lib-flexible --save npm install postcss-pxtorem --save-dev注意這里用的是postcss-pxtorem不是老教程里的px2rem-loader。px2rem-loader是 webpack loader 方案在 Vue CLI 4 和 Vite 里已經(jīng)不太適用了。postcss-pxtorem是 PostCSS 插件兼容性更好配置也更干凈。3.2 在 main.js 中引入 lib-flexible// main.js import Vue from vue import App from ./App.vue import lib-flexible/flexible.js Vue.config.productionTip false new Vue({ render: h h(App), }).$mount(#app)引入順序有講究lib-flexible/flexible.js要放在所有樣式和組件之前因?yàn)樗枰陧撁驿秩厩熬驮O(shè)置好根元素的 font-size。如果放在后面首屏可能會出現(xiàn)一瞬間的尺寸跳變。3.3 刪除 index.html 里的 viewport meta打開public/index.html找到這一行并刪掉!-- 刪除這行 -- meta nameviewport contentwidthdevice-width, initial-scale1.0lib-flexible 會自己根據(jù)設(shè)備 DPR 動態(tài)生成 viewport meta 標(biāo)簽。如果你手動保留了一個兩個 meta 會沖突導(dǎo)致縮放行為異常。這是很多人接入后真機(jī)顯示不對的首要原因。3.4 配置 postcss-pxtoremVue CLI 項(xiàng)目在根目錄創(chuàng)建或修改postcss.config.js// postcss.config.js module.exports { plugins: { postcss-pxtorem: { rootValue: 75, propList: [*], selectorBlackList: [.norem], minPixelValue: 2 } } }參數(shù)逐個說明參數(shù)作用建議值rootValue設(shè)計稿寬度 / 10750 稿填 75375 稿填 37.5propList需要轉(zhuǎn)換的屬性[*]表示全部轉(zhuǎn)換selectorBlackList不轉(zhuǎn)換的選擇器加.norem類可跳過minPixelValue小于該值不轉(zhuǎn)換填 2避免 1px 邊框被轉(zhuǎn)成 rem如果你用的是 Vite配置寫在vite.config.js里// vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import postcssPxtorem from postcss-pxtorem export default defineConfig({ plugins: [vue()], css: { postcss: { plugins: [ postcssPxtorem({ rootValue: 75, propList: [*], minPixelValue: 2 }) ] } } })3.5 特殊場景的寫法有些尺寸你不想被轉(zhuǎn)換。比如 1px 邊框轉(zhuǎn)成 rem 后在部分機(jī)型上會消失或變粗。這時候用PX大寫postcss-pxtorem 會跳過.card { width: 300px; /* 會被轉(zhuǎn)成 4rem */ border: 1PX solid #ddd; /* 保持 1px 不變 */ font-size: 28px; /* 會被轉(zhuǎn)成 0.3733rem */ }字體大小是否用 rem 取決于你的需求。用 rem 的好處是隨屏幕縮放壞處是在大屏手機(jī)上字會偏大。我的做法是正文用 rem標(biāo)題用PX固定避免大屏上標(biāo)題過于夸張。4. 驗(yàn)證請求與真機(jī)確認(rèn)適配生效配置改完重啟開發(fā)服務(wù)器npm run serve4.1 瀏覽器端快速驗(yàn)證打開 Chrome DevTools切到 iPhone 6/7/8375×667模式。在 Console 里輸入document.documentElement.style.fontSize如果返回37.5px說明 lib-flexible 生效了。再切到 iPhone 5320 寬應(yīng)該返回32px。切到 iPhone 14 Pro Max430 寬應(yīng)該返回43px。這個值始終等于屏幕邏輯寬度除以 10。再檢查一個元素的 computed style。找一個你寫了width: 150px的元素看它實(shí)際渲染的寬度是不是2rem對應(yīng)的像素值。在 375 屏上2rem 75px元素應(yīng)該占屏幕寬度的五分之一。4.2 真機(jī)驗(yàn)證步驟模擬器只能驗(yàn)證邏輯真機(jī)才能暴露 DPR 和 viewport 的問題。用手機(jī)連上同一局域網(wǎng)訪問開發(fā)服務(wù)器的 IP 地址。重點(diǎn)看三件事第一頁面有沒有出現(xiàn)橫向滾動條。如果有說明某個元素寬度超過了 100%通常是 padding 或 margin 沒算進(jìn)去。第二1px 邊框在真機(jī)上是否清晰。如果模糊或消失檢查是不是用了小寫px被轉(zhuǎn)成了 rem。第三旋轉(zhuǎn)屏幕后布局是否正常。lib-flexible 會監(jiān)聽 resize 事件重新計算但有些組件庫的彈窗可能不會跟著變需要手動觸發(fā)。4.3 用模型輔助檢查換算如果你有一批設(shè)計稿尺寸要批量轉(zhuǎn) rem可以把換算規(guī)則發(fā)給模型讓它幫你算。接入方式參考 https://taotoken.net/api對話入口在 https://taotoken.net/models。比如你告訴它「rootValue 是 75把 320px、48px、120px 轉(zhuǎn)成 rem」它會直接給出結(jié)果比手算快。5. 本篇常見錯誤排查5.1 根元素 font-size 始終是 0 或不變最常見的原因是flexible.js沒有正確引入。檢查 main.js 里的 import 路徑lib-flexible/flexible.js和lib-flexible是兩個不同的入口前者才會執(zhí)行初始化邏輯。另外確認(rèn)node_modules/lib-flexible目錄存在有時候 npm 裝包失敗但沒報錯。5.2 樣式里的 px 沒有被轉(zhuǎn)成 rem先確認(rèn)postcss.config.js的位置。Vue CLI 項(xiàng)目放在根目錄Vite 項(xiàng)目可以放在根目錄也可以在vite.config.js里內(nèi)聯(lián)。如果兩個地方都配了會沖突。其次檢查propList是否包含了你要轉(zhuǎn)的屬性默認(rèn)[*]是全轉(zhuǎn)但如果你改成了[width, height]那font-size就不會轉(zhuǎn)。還有一個隱蔽的坑node_modules里的第三方組件庫樣式默認(rèn)不會被 PostCSS 處理。如果你用了 Vant 或 Element UI 的移動端組件它們的 px 不會轉(zhuǎn)。解決辦法是在vue.config.js里配置transpileDependencies或者用selectorBlackList排除組件庫的類名。5.3 真機(jī)上字體過大或過小這是 rootValue 設(shè)錯了。750 的設(shè)計稿必須配 75如果你填了 37.5所有元素會縮小一半。反過來375 的稿填了 75元素會放大一倍。確認(rèn)你的設(shè)計稿寬度然后除以 10。5.4 橫屏?xí)r布局錯亂lib-flexible 默認(rèn)以豎屏寬度為基準(zhǔn)。橫屏?xí)r屏幕寬度變大rem 基準(zhǔn)值也跟著變大元素會被拉寬。如果你的頁面需要支持橫屏可以在 flexible.js 引入后手動覆蓋// 橫屏?xí)r以高度為基準(zhǔn) window.addEventListener(resize, () { if (window.orientation 90 || window.orientation -90) { document.documentElement.style.fontSize (window.innerHeight / 10) px } })5.5 首屏閃爍頁面加載時先按默認(rèn) font-size 渲染然后 flexible.js 執(zhí)行后重新計算導(dǎo)致一瞬間的尺寸跳變。解決辦法是在 index.html 的head里內(nèi)聯(lián)一段腳本在 CSS 加載前就設(shè)置好 font-sizescript (function() { var width document.documentElement.clientWidth || window.innerWidth document.documentElement.style.fontSize (width / 10) px })() /script這段腳本要放在所有 CSS 之前這樣首屏渲染時根元素尺寸就是對的。6. 后續(xù)開發(fā)與工具鏈銜接適配配置跑通之后日常開發(fā)還有幾件事可以提前做。第一在 VS Code 里裝cssrem插件設(shè)置cssrem.rootFontSize為 75寫 px 時它會實(shí)時提示對應(yīng)的 rem 值不用手算。第二把常用的間距、字號抽成 SCSS 變量統(tǒng)一用 rem 單位避免散落在各個組件里。第三如果項(xiàng)目要長期維護(hù)考慮把適配邏輯封裝成一個獨(dú)立的 composable 或 mixin方便在多個項(xiàng)目間復(fù)用。如果你在接入過程中遇到報錯或者想讓模型幫你審查 postcss 配置可以走 API Keys 頁面拿 Key 后接入https://taotoken.net/console/api-keys接入文檔在 https://taotoken.net/api。長期做移動端編碼的話Coding Plan 的額度更劃算https://taotoken.net/coding-plan。Claude Code 的接入方式參考https://taotoken.net/claude-code。最后提醒一句lib-flexible 已經(jīng)停止維護(hù)但它的方案足夠穩(wěn)定在存量項(xiàng)目里仍然是主流選擇。新項(xiàng)目可以考慮postcss-px-to-viewport走 vw 方案原理類似但不需要 JS 運(yùn)行時。選哪個取決于你的團(tuán)隊習(xí)慣和瀏覽器兼容要求。