久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

Vue 性能優(yōu)化:Forced reflow 排查與讀寫分離實(shí)戰(zhàn)

Vue 性能優(yōu)化:Forced reflow 排查與讀寫分離實(shí)戰(zhàn) 控制臺(tái)里突然刷出一屏[Violation] Forced reflow while executing JavaScript took 87ms然后頁(yè)面滾一下來(lái)一條、點(diǎn)一下來(lái)一條開(kāi)發(fā)機(jī)上還沒(méi)什么感覺(jué)一上真機(jī)就開(kāi)始滑動(dòng)粘手打字掉幀——這個(gè)場(chǎng)景做 Vue 的同學(xué)基本都躲不掉。這條警告不是報(bào)錯(cuò)不影響功能所以它常年被埋在日志里沒(méi)人管但它幾乎是所有頁(yè)面越用越卡問(wèn)題的第一現(xiàn)場(chǎng)。它說(shuō)的是一件很具體的事JavaScript 執(zhí)行過(guò)程中觸發(fā)了強(qiáng)制同步重排Forced reflow瀏覽器為了把最新的布局?jǐn)?shù)據(jù)交還給你被迫中斷當(dāng)前 JS 執(zhí)行提前把渲染流水線跑了一遍這一趟花了 87 毫秒。而 87 毫秒在 60 幀的節(jié)奏里等于你連丟五幀還多。這篇文章想解決的就是這一類問(wèn)題Vue 項(xiàng)目里為什么特別容易踩到 Forced reflow、怎么用 DevTools 把它釘?shù)骄唧w那一行代碼、讀寫分離到底該怎么寫、第三方庫(kù)和動(dòng)畫場(chǎng)景怎么繞過(guò)去。內(nèi)容偏實(shí)戰(zhàn)代碼可以整段抄走改適合寫過(guò)一兩個(gè) Vue 項(xiàng)目、開(kāi)始關(guān)心性能但還沒(méi)系統(tǒng)整理過(guò)渲染流程的同學(xué)如果你只是想知道警告關(guān)掉行不行那答案是不行后面會(huì)說(shuō)為什么。1. 先把這條警告翻譯成人話1.1 瀏覽器渲染一幀要經(jīng)過(guò)哪幾步現(xiàn)代瀏覽器的渲染主流程可以粗略拆成五段JavaScript 執(zhí)行 → 樣式計(jì)算Style / Recalculate Style→ 布局Layout也就是重排 / Reflow→ 繪制Paint→ 合成Composite。JS 階段你改 DOM、改 class、改 inline style樣式計(jì)算把 CSS 規(guī)則解析成每個(gè)元素最終的計(jì)算樣式布局拿到計(jì)算樣式后算出每個(gè)盒子在頁(yè)面上的精確位置和尺寸繪制把盒子變成像素指令合成把這些指令按圖層拼成你看到的畫面。關(guān)鍵點(diǎn)在于布局這一步是惰性的。你在 JS 里改了el.style.width 200px瀏覽器不會(huì)立刻重算布局它只會(huì)在內(nèi)部標(biāo)記這個(gè)元素的布局臟了然后攢著。攢到什么時(shí)候攢到兩種時(shí)刻一是真的要畫下一幀了二是有代碼來(lái)問(wèn)它要布局結(jié)果。后者就是災(zāi)難的起點(diǎn)。因?yàn)橐坏┠銌?wèn)它要布局結(jié)果它沒(méi)法用舊數(shù)據(jù)糊弄你舊數(shù)據(jù)已經(jīng)過(guò)期了只能立刻停下來(lái)把樣式計(jì)算和布局全部跑完再把答案給你。這中間你的 JS 是被打斷的主線程被布局占滿這就是同步重排。所謂 Forced重點(diǎn)在被迫——瀏覽器本來(lái)想拖到幀末一起算的被你逼著提前算了。1.2 到底哪些操作會(huì)逼瀏覽器重排能觸發(fā)強(qiáng)制重排的操作本質(zhì)都是讀取幾何信息。這些屬性不是存在元素身上的靜態(tài)值而是布局算完才有的結(jié)果所以讀它們就等于向?yàn)g覽器要賬。常見(jiàn)的清單如下觸發(fā)源典型寫法說(shuō)明偏移尺寸offsetTopoffsetLeftoffsetWidthoffsetHeight最常被踩的一類循環(huán)里讀它等于開(kāi)重排循環(huán)客戶區(qū)尺寸clientWidthclientHeightclientTopclientLeft不含邊框常用于算滾動(dòng)容器可視高度滾動(dòng)尺寸與位置scrollTopscrollLeftscrollWidthscrollHeight寫scrollTop是寫操作但連著讀就會(huì)交替幾何矩形getBoundingClientRect()getClientRects()定位類組件、拖拽、Tooltip 全靠它計(jì)算樣式getComputedStyle(el).width等布局相關(guān)屬性讀color未必觸發(fā)讀width必觸發(fā)CSS 變量getComputedStyle(el).getPropertyValue(--x)變量參與了布局計(jì)算時(shí)同樣要 flush焦點(diǎn)與滾動(dòng)定位element.focus()scrollIntoView()內(nèi)部需要知道元素位置才能滾動(dòng)Range 相關(guān)range.getBoundingClientRect()富文本編輯器里非常常見(jiàn)這里有個(gè)非常重要的判斷標(biāo)準(zhǔn)很多人搞混連續(xù)讀是安全的連續(xù)寫也是安全的只有讀寫交替才致命。你一口氣讀一百個(gè)元素的offsetHeight瀏覽器只會(huì)重排一次因?yàn)榈谝淮巫x之后布局就是干凈的剩下的讀都在用同一份新鮮數(shù)據(jù)你一口氣寫一百個(gè)元素的寬高瀏覽器一次都不重排因?yàn)椴季直煌七t到幀末。但你要是讀一個(gè)、寫一個(gè)、再讀一個(gè)、再寫一個(gè)那就是一百次完整重排。注意console.log(el.offsetWidth)這種調(diào)試語(yǔ)句本身就是讀操作。有時(shí)候你只是加了幾行日志想看看尺寸警告就冒出來(lái)了別把這個(gè)鍋甩給業(yè)務(wù)代碼。1.3 警告里那個(gè) took 87ms 是怎么來(lái)的Chrome 會(huì)把每一次強(qiáng)制布局的耗時(shí)算出來(lái)超過(guò)一定閾值經(jīng)驗(yàn)上單次幾十毫秒級(jí)別就會(huì)在控制臺(tái)記一條 Violation。數(shù)字越大說(shuō)明這次重排的代價(jià)越離譜。為什么能這么大因?yàn)橐淮沃嘏挪恢皇撬隳氵@一個(gè)元素布局的波及范圍可能是整棵子樹(shù)甚至整個(gè)文檔。改了外層容器的寬度里面所有依賴百分比的子元素、所有的文本換行、所有的 flex/grid 分配都要跟著重算。一個(gè)幾千行的表格一次重排干到幾十毫秒一點(diǎn)都不夸張。更麻煩的是它會(huì)累積。你在mousemove里搞一次強(qiáng)制重排鼠標(biāo)移動(dòng)一秒觸發(fā)六十次那就是六十次重排主線程被切成碎片用戶看到的就是拖拽跟不上手。單看一條警告好像無(wú)所謂乘上觸發(fā)頻率就是災(zāi)難。2. Vue 項(xiàng)目為什么格外容易踩這個(gè)坑2.1 響應(yīng)式更新的批處理救了你也騙了你Vue 3 的更新是異步批處理的你在一個(gè) tick 里改了十個(gè)ref它只會(huì)在微任務(wù)隊(duì)列里 flush 一次patch一次 DOM。這本身是非常好的設(shè)計(jì)它天然把寫集中起來(lái)了。問(wèn)題出在讀上——Vue 只幫你批處理了寫沒(méi)管你的讀。于是很常見(jiàn)的寫法就變成了這樣組件里某個(gè)方法先改了一個(gè)狀態(tài)然后await nextTick()接著遍歷 DOM 子節(jié)點(diǎn)讀尺寸讀完根據(jù)尺寸再改一次狀態(tài)。這一輪下來(lái)寫、讀、寫交替得非常干凈每一次讀都在逼瀏覽器 flush。而且因?yàn)?Vue 的patch是深度優(yōu)先遍歷虛擬 DOM一個(gè)父組件的更新可能牽動(dòng)幾十個(gè)子組件同時(shí)掛載你在onMounted里讀一次尺寸就是幾十次讀擠在同一幀如果中間還夾雜著子組件的寫操作交替就發(fā)生了。還有一個(gè)隱蔽的點(diǎn)Vue 的nextTick用的是微任務(wù)Promise.then它跑在瀏覽器渲染之前的任意時(shí)刻跟幀的節(jié)奏沒(méi)關(guān)系。你在微任務(wù)里讀布局瀏覽器一樣得立刻滿足你。所以nextTick不是等渲染完它只是等 DOM 更新完DOM 更新完不代表布局算完了。這個(gè)區(qū)別決定了你很多我已經(jīng)nextTick了為什么還有警告的困惑。2.2 組件化本身會(huì)制造隱形讀寫交替單文件組件寫多了你很難一眼看出哪里在讀哪里在寫因?yàn)樽x寫散落在不同組件里。舉個(gè)我真實(shí)遇到過(guò)的例子一個(gè)父組件列表子組件里有個(gè)mounted鉤子用于根據(jù)自身寬度決定標(biāo)題要不要省略號(hào)。子組件掛載時(shí)會(huì)讀自己的clientWidth而父組件在插入這些子組件之前剛剛設(shè)置過(guò)容器的padding。結(jié)果就是子組件每掛載一個(gè)讀一次寬度而父組件的樣式寫入又讓布局臟掉下一個(gè)子組件讀的時(shí)候又得重排。一百個(gè)子組件就是一百次重排控制臺(tái)刷屏。這種問(wèn)題在組件層級(jí)越深、復(fù)用越多的項(xiàng)目里越嚴(yán)重因?yàn)閷懖僮靼l(fā)生在祖先讀操作發(fā)生在后代中間隔著好幾層組件邊界你根本不會(huì)把它們聯(lián)系起來(lái)。這也是為什么我認(rèn)為這條警告不能只靠看到就改得建立一個(gè)意識(shí)任何讀 DOM 尺寸的代碼都要問(wèn)一句我前面有沒(méi)有剛寫過(guò)樣式。2.3 Transition 和動(dòng)畫鉤子里的固定開(kāi)銷Vue 的Transition在實(shí)現(xiàn)上為了拿到過(guò)渡起點(diǎn)需要在元素插入后、添加過(guò)渡類名之前讀取一次布局信息這個(gè)操作本身就會(huì)強(qiáng)制重排。單個(gè)元素?zé)o所謂一兩個(gè)毫秒的事但列表過(guò)濾、v-show批量切換、路由切換帶動(dòng)畫的時(shí)候同一幀內(nèi)可能有幾十個(gè)元素同時(shí)走這套流程代價(jià)就上來(lái)了。v-show還有額外一層display: none和display: block的切換會(huì)直接讓布局失效切完再去讀尺寸就是一次完整重排。有些同學(xué)為了做折疊展開(kāi)動(dòng)畫用v-show配合讀取內(nèi)容高度在長(zhǎng)列表里滾動(dòng)著展開(kāi)卡頓感會(huì)非常明顯。2.4 第三方庫(kù)是重災(zāi)區(qū)而且你往往改不動(dòng)ECharts、Swiper、各類拖拽庫(kù)、虛擬表格、富文本編輯器這些庫(kù)的定位邏輯基本都建立在getBoundingClientRect()上。它們初始化的時(shí)候要量容器尺寸resize的時(shí)候要重新量彈出面板的時(shí)候要算位置。你沒(méi)法改它們的源碼只能從兩個(gè)方向下手控制調(diào)用時(shí)機(jī)和控制調(diào)用頻率。時(shí)機(jī)上別在mounted同步初始化一屏幾十個(gè)圖表讓它們?cè)趓equestAnimationFrame里排隊(duì)頻率上resize回調(diào)必須防抖而且防抖的落地方式最好是rAF節(jié)流加時(shí)間閾值不是簡(jiǎn)單的setTimeout。這部分在第 5 節(jié)會(huì)展開(kāi)寫具體代碼。3. 把這個(gè)警告釘?shù)骄唧w那一行代碼3.1 Performance 面板的正確讀法控制臺(tái)的 Violation 只告訴你發(fā)生了不告訴你在哪。真正定位得靠 Performance 面板。操作步驟是打開(kāi) DevTools切到 Performance點(diǎn)左上角的錄制按鈕然后在頁(yè)面上復(fù)現(xiàn)卡頓操作滾動(dòng)、拖拽、切換列表三五秒后停止錄制。拿到火焰圖之后看頂上那幾條橫軸色塊。紫色偏藍(lán)的是 Layout布局深紫偏紅的是 Recalculate Style。如果你看到一串密密麻麻的小紫色塊每個(gè)都很短但數(shù)量巨大中間還夾著黃色Scripting的小塊那就是典型的 layout thrashing——讀寫交替的指紋。如果是一個(gè)巨大的紫色塊那說(shuō)明是單次重排范圍太大方向就不一樣了該考慮的是減少布局波及面比如contain、content-visibility。再往下看切換到 Bottom-Up 或者 Call Tree 視圖按 Self Time 排序。通常在紫色塊下面能直接看到你的業(yè)務(wù)函數(shù)名點(diǎn)進(jìn)去就能定位到源碼行。如果看到的是一堆getBoundingClientRect、offsetHeight之類的原生調(diào)用展開(kāi)它的調(diào)用棧業(yè)務(wù)代碼一定在里面。3.2 用代碼給自己埋點(diǎn)抓出超時(shí)的那一次Performance 面板好用但它只能事后看而且信息量大、有學(xué)習(xí)成本。想快速定位我習(xí)慣直接給關(guān)鍵 API 打個(gè)補(bǔ)丁統(tǒng)計(jì)每次耗時(shí)和調(diào)用棧。這段代碼只在開(kāi)發(fā)環(huán)境加上線前刪掉或包在if (import.meta.env.DEV)里// dev-perf.js —— 只在開(kāi)發(fā)環(huán)境引入 if (import.meta.env.DEV) { const wrap (obj, name) { const raw obj[name] if (typeof raw ! function) return obj[name] function (...args) { const t0 performance.now() const result raw.apply(this, args) const cost performance.now() - t0 // 閾值可以調(diào)抓大放小 if (cost 5) { console.warn([slow ${name}] ${cost.toFixed(1)}ms, this) console.trace() } return result } } wrap(Element.prototype, getBoundingClientRect) wrap(Element.prototype, getClientRects) wrap(Range.prototype, getBoundingClientRect) // 幾何屬性是 getter用 defineProperty 包一層 const geometryProps [offsetWidth, offsetHeight, offsetTop, offsetLeft, clientWidth, clientHeight, scrollWidth, scrollHeight] geometryProps.forEach((prop) { const owner prop.startsWith(scroll) ? Element.prototype : HTMLElement.prototype const desc Object.getOwnPropertyDescriptor(owner, prop) if (!desc || !desc.get) return Object.defineProperty(owner, prop, { ...desc, get() { const t0 performance.now() const value desc.get.call(this) const cost performance.now() - t0 if (cost 5) { console.warn([slow read ${prop}] ${cost.toFixed(1)}ms, this) console.trace() } return value } }) }) }這里有個(gè)細(xì)節(jié)值得說(shuō)offsetWidth這類屬性是getter不是方法所以不能像getBoundingClientRect那樣直接替換函數(shù)得用Object.getOwnPropertyDescriptor拿到原始 getter 再包一層。另外注意scrollWidth掛在Element上offsetWidth掛在HTMLElement上掛錯(cuò)原型鏈會(huì)報(bào)錯(cuò)我上面做了個(gè)簡(jiǎn)單區(qū)分。埋點(diǎn)閾值別設(shè)太小5ms 以下的不看。跑一遍頁(yè)面控制臺(tái)會(huì)直接告訴你哪一行慢、調(diào)用棧是什么比在火焰圖里翻半天高效得多。3.3 一張現(xiàn)場(chǎng)排查清單真到了線上或者別人移交的項(xiàng)目里時(shí)間緊不可能慢慢打補(bǔ)丁。我整理了一張按現(xiàn)象反推原因的表先對(duì)號(hào)入座再動(dòng)手現(xiàn)場(chǎng)現(xiàn)象大概率原因第一步做什么拖拽/鼠標(biāo)跟隨明顯延遲mousemove里讀getBoundingClientRect并寫樣式把讀取挪到mousedown移動(dòng)過(guò)程只寫transform長(zhǎng)列表滾動(dòng)頓挫列表項(xiàng)內(nèi)讀offsetTop做吸附/瀑布流改用IntersectionObserver或緩存偏移量輸入框打字掉幀input事件里讀scrollHeight做高度自適應(yīng)用rAF節(jié)流 textarea的field-sizing或緩存彈層/下拉定位抖動(dòng)Popper 類庫(kù)在滾動(dòng)事件里持續(xù)測(cè)量限制resize/scroll觸發(fā)源或用 CSS 定位一屏圖表初始化時(shí)白屏卡住多個(gè)圖表mounted同步初始化爭(zhēng)搶主線程用rAF分批初始化配合骨架屏折疊展開(kāi)動(dòng)畫卡v-show切換后立刻讀內(nèi)容高度改v-if加緩存高度或用grid-template-rows動(dòng)畫窗口拉伸時(shí)整體卡頓resize回調(diào)沒(méi)防抖全量重排rAF節(jié)流只在幀內(nèi)算一次這張表覆蓋了八成左右的常見(jiàn)情況。如果你遇到的警告既不屬于拖拽也不屬于滾動(dòng)那大概率是某個(gè)第三方組件的初始化或resize用第 3.2 節(jié)的埋點(diǎn)腳本跑一遍最快。4. 核心解藥讀寫分離到底怎么做4.1 為什么讀寫分離能根治原理其實(shí)一句話把同一幀內(nèi)所有的讀集中在前半段所有的寫集中在后半段讀之前保證布局是干凈的寫之后不再去問(wèn)布局要數(shù)據(jù)。這樣一幀內(nèi)最多強(qiáng)制重排一次甚至零次如果讀的時(shí)候沒(méi)有臟布局。這套思路業(yè)界叫 fastdom名字來(lái)自 FastDOM 這個(gè)庫(kù)核心就是一個(gè)兩階段隊(duì)列measure放讀任務(wù)mutate放寫任務(wù)統(tǒng)一調(diào)度。自己實(shí)現(xiàn)一個(gè)簡(jiǎn)化版完全夠用五十行以內(nèi)。4.2 一個(gè)可以直接抄的調(diào)度器// scheduler.js const readQueue [] const writeQueue [] let rafId 0 let flushing false function flush() { rafId 0 flushing true // 第一階段集中讀此時(shí)布局應(yīng)當(dāng)是最新的 const reads readQueue.splice(0) for (let i 0; i reads.length; i) { try { reads[i]() } catch (e) { console.error(e) } } // 第二階段集中寫寫操作不會(huì)立刻觸發(fā)重排 const writes writeQueue.splice(0) for (let i 0; i writes.length; i) { try { writes[i]() } catch (e) { console.error(e) } } flushing false // 寫入過(guò)程中如果又產(chǎn)生了新的任務(wù)常見(jiàn)于寫里嵌套了讀排到下一幀 if (readQueue.length || writeQueue.length) schedule() } function schedule() { if (rafId) return rafId requestAnimationFrame(flush) } export function measure(fn) { readQueue.push(fn) // 關(guān)鍵如果當(dāng)前不在 flush 中說(shuō)明還沒(méi)到幀可以立即安排 // 如果正在寫階段追加讀任務(wù)絕不能同步執(zhí)行否則立刻退化成 thrashing schedule() } export function mutate(fn) { writeQueue.push(fn) if (!flushing) schedule() }有三個(gè)地方是我踩過(guò)坑之后特意加固的第一schedule用requestAnimationFrame而不是微任務(wù)。微任務(wù)在當(dāng)前宏任務(wù)結(jié)束時(shí)就跑了可能還在同一幀的 JS 階段里讀到的布局照樣要 flushrAF回調(diào)發(fā)生在瀏覽器決定要渲染這一幀的時(shí)刻此時(shí)上一輪寫入的樣式已經(jīng)被瀏覽器納入計(jì)算讀起來(lái)更干凈。第二用一個(gè)flushing標(biāo)志判斷當(dāng)前階段。如果mutate階段的函數(shù)里又調(diào)了measure絕對(duì)不能同步執(zhí)行那個(gè)讀否則你精心設(shè)計(jì)的讀寫分離當(dāng)場(chǎng)失效。我的做法是讓它在flush結(jié)束時(shí)檢測(cè)隊(duì)列非空重新排一幀。第三每個(gè)任務(wù)包try/catch。調(diào)度器是全局的一個(gè)任務(wù)拋錯(cuò)不能拖垮整批任務(wù)線上排查時(shí)這一點(diǎn)很關(guān)鍵。4.3 在 Vue 組件里怎么落地有了調(diào)度器業(yè)務(wù)代碼的改法就很機(jī)械了——把讀包進(jìn)measure把寫包進(jìn)mutate。但 Vue 里有幾個(gè)地方要注意。第一不要在measure回調(diào)里直接改響應(yīng)式狀態(tài)。改狀態(tài)會(huì)觸發(fā) Vue 的更新調(diào)度雖然它也是異步的但在這個(gè)上下文里容易讓數(shù)據(jù)流變得不可預(yù)測(cè)。清爽的做法是讀階段把結(jié)果收集到一個(gè)普通對(duì)象里寫階段再拿這些數(shù)據(jù)統(tǒng)一提交給 Vue。第二await nextTick()之后不要直接讀尺寸。正確的姿勢(shì)是import { nextTick } from vue import { measure, mutate } from ./scheduler async function syncLayout() { await nextTick() // 等 DOM 更新完 measure(() { // 再等一個(gè)渲染幀讀干凈布局 const items [...listRef.value.children] const heights items.map(el el.offsetHeight) // 連續(xù)讀只重排一次 mutate(() { items.forEach((el, i) { el.style.setProperty(--row-h, heights[i] px) // 連續(xù)寫 }) }) }) }注意這里讀和寫的順序先nextTick保證 DOM 存在再measure保證布局新鮮讀的時(shí)候用map一次性收集完不要在循環(huán)里寫然后mutate里批量寫。這套流程下來(lái)整個(gè)函數(shù)最多觸發(fā)一次強(qiáng)制重排。第三組件卸載時(shí)要清理。調(diào)度器是模塊級(jí)的如果組件卸載后隊(duì)列里還有引用著已銷毀 DOM 的回調(diào)讀的時(shí)候就會(huì)拿到null。我的處理是在回調(diào)里做空值判斷或者給任務(wù)加一個(gè)cancelled標(biāo)記在onUnmounted里置位。4.4 什么情況下不用調(diào)度器直接 rAF 就夠調(diào)度器解決的是多個(gè)模塊零散讀寫的問(wèn)題。如果你只有一個(gè)函數(shù)讀寫都在里面那直接requestAnimationFrame更輕let pending false let cachedRect null function onScroll() { if (!pending) { pending true requestAnimationFrame(() { pending false // 這里集中做讀寫注意讀必須放在寫前面 const top container.getBoundingClientRect().top sticky.style.transform top 0 ? translateY(${-top}px) : none }) } }這個(gè)模式叫rAF 節(jié)流本質(zhì)上是把一個(gè)高頻事件壓縮成每幀最多執(zhí)行一次。它在滾動(dòng)、拖拽、mousemove、resize場(chǎng)景里幾乎是萬(wàn)能的代碼量小、沒(méi)有依賴建議先把這個(gè)用起來(lái)再考慮上調(diào)度器。提示resize事件還有個(gè)更現(xiàn)代的替代品ResizeObserver。它比window上的resize精準(zhǔn)得多能觀察單個(gè)元素但要注意它的回調(diào)本身也是布局之后、繪制之前執(zhí)行回調(diào)里讀尺寸是安全的寫尺寸卻可能觸發(fā)循環(huán)。要寫就包一層rAF或者直接在回調(diào)里做防抖。5. 高頻場(chǎng)景逐個(gè)擊破5.1 拖拽把讀取挪到事件開(kāi)始那一刻拖拽是 Forced reflow 的頭號(hào)來(lái)源。壞的寫法幾乎人人寫過(guò)// 反面教材每一幀都在讀寫交替 function onMouseMove(e) { const rect box.getBoundingClientRect() // 讀強(qiáng)制重排 box.style.left rect.left e.movementX px // 寫布局臟了 box.style.top rect.top e.movementY px }每一次mousemove都是讀一次、寫一次而且讀的還是自己剛剛寫臟的元素重排跑不掉了。正確做法是把狀態(tài)存在變量里事件開(kāi)始時(shí)讀一次移動(dòng)過(guò)程純計(jì)算加寫const state { startX: 0, startY: 0, originLeft: 0, originTop: 0, moving: false, x: 0, y: 0 } let rafId 0 function onMouseDown(e) { const rect box.getBoundingClientRect() // 整個(gè)拖拽過(guò)程只讀這一次 state.startX e.clientX state.startY e.clientY state.originLeft rect.left state.originTop rect.top state.moving true document.addEventListener(mousemove, onMouseMove) } function onMouseMove(e) { if (!state.moving) return state.x state.originLeft (e.clientX - state.startX) state.y state.originTop (e.clientY - state.startY) if (!rafId) rafId requestAnimationFrame(paint) } function paint() { rafId 0 // 用 translate3d 而不是 left/top box.style.transform translate3d(${state.x}px, ${state.y}px, 0) }兩個(gè)改動(dòng)帶來(lái)兩個(gè)收益第一整個(gè)拖拽只強(qiáng)制重排一次第二用transform替代left/top元素在合成層上移動(dòng)連布局和繪制都省了只剩下合成流暢度是數(shù)量級(jí)的差別。這個(gè)技巧是我做拖拽交互時(shí)最常用的一招記住動(dòng)位置用 transform不動(dòng) left/top基本能躲掉一半的卡頓。5.2 長(zhǎng)列表與虛擬滾動(dòng)v-for渲染幾千條數(shù)據(jù)然后在某個(gè)方法里遍歷子元素讀offsetTop這是瀑布流和吸附滾動(dòng)的經(jīng)典寫法也是經(jīng)典的重排炸彈。改法有兩條路。輕量的一條是緩存加批量在列表數(shù)據(jù)變化之后用一個(gè)measure任務(wù)一次性把所有子元素的偏移量讀出來(lái)存到數(shù)組里之后滾動(dòng)過(guò)程中只查數(shù)組不碰 DOM。注意這個(gè)緩存要在容器尺寸變化時(shí)失效重建ResizeObserver是合適的鉤子。徹底的一條是上虛擬滾動(dòng)。虛擬滾動(dòng)的核心思想是只渲染視口內(nèi)的元素元素?cái)?shù)量從幾千降到幾十任何遍歷操作的代價(jià)都變得可以接受。如果要自己實(shí)現(xiàn)關(guān)鍵點(diǎn)是行高固定或提前測(cè)量、用絕對(duì)定位撐開(kāi)滾動(dòng)高度、滾動(dòng)事件用rAF節(jié)流。行高不固定的場(chǎng)景通常做法是先按估算行高渲染再用ResizeObserver或者measure任務(wù)逐個(gè)修正真實(shí)高度并回填緩存。對(duì)于大多數(shù)業(yè)務(wù)項(xiàng)目我建議直接用成熟庫(kù)而不是自己寫。選庫(kù)的時(shí)候看一眼它在滾動(dòng)過(guò)程中有沒(méi)有讀取getBoundingClientRect有的庫(kù)為了做滾動(dòng)到指定項(xiàng)會(huì)在每次滾動(dòng)時(shí)測(cè)量那就得配個(gè)節(jié)流。5.3 動(dòng)畫優(yōu)先動(dòng)不會(huì)觸發(fā)布局的屬性做動(dòng)畫有一條鐵律只動(dòng)transform和opacity其他屬性盡量別碰。原因是這兩個(gè)屬性在合成階段處理改它們不會(huì)引起樣式重算和布局重排而改width、height、margin、padding、top、left、font-size這些必然重排而且很可能牽連一大片。Vue 的Transition默認(rèn)用的是opacity和transform之外的類名切換所以自定義過(guò)渡的時(shí)候要自己寫對(duì)。常見(jiàn)的折疊展開(kāi)如果想平滑別用height: 0到height: autoauto沒(méi)法過(guò)渡而且會(huì)重排用grid-template-rows: 0fr到1fr或者transform: scaleY加transform-origin。前者是純粹的小技巧兼容性不錯(cuò)。如果用 Vue 的 JS 鉤子做動(dòng)畫before-enter、enter這類記得每次在enter回調(diào)里做一次el.offsetHeight強(qiáng)制重排來(lái)激活過(guò)渡這是標(biāo)準(zhǔn)做法但別在循環(huán)里對(duì)幾十個(gè)元素同時(shí)做。批量過(guò)渡的場(chǎng)景我通常改成 CSS 類切換加transition-delay錯(cuò)開(kāi)讓瀏覽器自己安排。5.4 第三方庫(kù)控時(shí)機(jī)、控頻率、控范圍第三方庫(kù)有三個(gè)可下手的地方。控時(shí)機(jī)指不要在mounted里同步初始化。一屏十個(gè)圖表每個(gè)初始化都要量容器、算布局堆在一起就是幾百毫秒。把它們?nèi)M(jìn)rAF或者用IntersectionObserver做進(jìn)視口才初始化onMounted(() { const io new IntersectionObserver((entries) { entries.forEach((entry) { if (!entry.isIntersecting) return io.unobserve(entry.target) requestAnimationFrame(() initChart(entry.target)) }) }, { rootMargin: 200px }) chartEls.value.forEach(el io.observe(el)) })rootMargin: 200px是提前量用戶還沒(méi)滾到就初始化完了體驗(yàn)更順??仡l率指給庫(kù)的resize、scroll回調(diào)加節(jié)流。很多庫(kù)自己不做這件事。如果它的 API 允許傳回調(diào)就在外面包一層rAF節(jié)流如果它是監(jiān)聽(tīng)window.resize的可以自己在初始化前先把尺寸算好傳進(jìn)去減少它內(nèi)部測(cè)量的次數(shù)??胤秶赣?CSS 限制布局的波及面下一節(jié)講。5.5 CSS 側(cè)的兩個(gè)低成本優(yōu)化contain屬性可以讓瀏覽器知道這個(gè)元素的內(nèi)部布局不影響外部從而把重排范圍鎖在局部。常用值是contain: layout paint布局和繪制都不外溢列表項(xiàng)、卡片、彈層都很適合加。加了之后改動(dòng)內(nèi)部的尺寸不會(huì)引起整個(gè)頁(yè)面的布局重算收益非常直接。content-visibility: auto更進(jìn)一步讓屏幕外元素的渲染被跳過(guò)。長(zhǎng)文檔、長(zhǎng)列表里效果明顯但要配contain-intrinsic-size給它一個(gè)占位尺寸否則滾動(dòng)條會(huì)跳。這兩個(gè)屬性現(xiàn)代瀏覽器都支持得不錯(cuò)屬于加一行、收益立竿見(jiàn)影的類型。還有will-change: transform很多人拿它當(dāng)萬(wàn)金油到處加。它的作用是提前把元素提升為獨(dú)立合成層減少動(dòng)畫過(guò)程中的重排和重繪。但別濫用——每個(gè)合成層都要占顯存幾十上百個(gè)層會(huì)把內(nèi)存吃光反而更卡。我的習(xí)慣是只在確實(shí)要做高頻動(dòng)畫的元素上加動(dòng)畫結(jié)束就移除。6. 常見(jiàn)問(wèn)題與避坑速查6.1 問(wèn)題速查表問(wèn)題原因解決nextTick之后讀尺寸仍報(bào)警告nextTick是微任務(wù)不等渲染幀讀操作包進(jìn)rAF或調(diào)度器單個(gè)元素動(dòng)畫也報(bào)警告動(dòng)畫屬性觸發(fā)了布局width/height/top改用transform/opacity只在低端機(jī)上卡高端機(jī)重排耗時(shí)低低于閾值不報(bào)用 Performance 面板看別依賴控制臺(tái)加了will-change反而更卡合成層數(shù)量過(guò)多占顯存只在動(dòng)畫期間加結(jié)束后移除resize里代碼很少也卡沒(méi)節(jié)流一次拉伸觸發(fā)幾十次用rAF節(jié)流并加最小間隔生產(chǎn)環(huán)境沒(méi)有警告Violation 只在 DevTools 打開(kāi)時(shí)采集生產(chǎn)排查靠 Performance 性能指標(biāo)組件卸載后報(bào)錯(cuò)調(diào)度隊(duì)列里的回調(diào)引用了已銷毀 DOM回調(diào)內(nèi)判空或加取消標(biāo)記列表用index做 key 更卡復(fù)用錯(cuò)位導(dǎo)致大量 DOM 重建用穩(wěn)定的業(yè)務(wù) id 做 key6.2 幾個(gè)容易搞反的細(xì)節(jié)第一個(gè)反直覺(jué)的點(diǎn)getComputedStyle讀color、font-weight這類純繪制屬性通常不會(huì)觸發(fā)重排但讀width、height、margin這些布局屬性一定觸發(fā)。所以別一看到getComputedStyle就緊張看你讀的是哪個(gè)屬性。第二個(gè)scrollTop的讀取是重排的來(lái)源之一但對(duì)滾動(dòng)容器來(lái)說(shuō)它更常見(jiàn)的坑是讀scrollHeight算總高。這個(gè)屬性依賴全部子元素布局代價(jià)很高能緩存就緩存。第三個(gè)v-if和v-show在這件事上的表現(xiàn)不同。v-if是增刪節(jié)點(diǎn)插入新節(jié)點(diǎn)必然讓布局臟掉v-show是切換display同樣讓布局臟掉。兩者都不省區(qū)別在渲染成本和狀態(tài)保持上別指望用v-show能繞開(kāi)重排。第四個(gè)offsetTop是相對(duì)于offsetParent的不是相對(duì)于視口。很多同學(xué)算錯(cuò)位置是因?yàn)闆](méi)注意offsetParent會(huì)被position: relative的祖先改變。算視口坐標(biāo)老老實(shí)實(shí)用getBoundingClientRect。6.3 我在實(shí)際項(xiàng)目里踩過(guò)的坑第一個(gè)坑是埋點(diǎn)本身拖慢了頁(yè)面。有一段時(shí)間我在Element.prototype上包了好幾層補(bǔ)丁本地跑得好好的一上真機(jī)開(kāi)發(fā)包就卡成幻燈片。原因是補(bǔ)丁里的performance.now()和console.trace()本身開(kāi)銷就不小console.trace()尤其重在mousemove高頻場(chǎng)景里直接拖垮主線程。后來(lái)我改成只在超過(guò)閾值且做了采樣比如每 20 次記錄一次的情況下才打日志問(wèn)題就沒(méi)了。第二個(gè)坑是調(diào)度器里的死循環(huán)。我最初的版本在flush結(jié)束時(shí)無(wú)條件重新schedule()結(jié)果一個(gè)任務(wù)里不斷往隊(duì)列里塞新任務(wù)把rAF變成了忙循環(huán)頁(yè)面反而更卡。后來(lái)加了單幀最多迭代兩次的限制超出的任務(wù)順著排到下一幀才穩(wěn)下來(lái)。第三個(gè)坑是以為transform是萬(wàn)能藥。transform確實(shí)不觸發(fā)布局但如果它作用的元素上有一個(gè)filter或者復(fù)雜的box-shadow照樣會(huì)觸發(fā)重繪代價(jià)并不低。還有transform會(huì)影響position: fixed子元素的定位基準(zhǔn)做全屏遮罩的時(shí)候要特別注意。第四個(gè)坑比較隱蔽document.body上的 class 切換會(huì)引發(fā)全頁(yè)重排。項(xiàng)目里做主題切換、字號(hào)切換的時(shí)候我在body上切了個(gè) class里面包含font-size變量結(jié)果整頁(yè)所有文本重新?lián)Q行一次重排上百毫秒。后來(lái)改成用 CSS 變量配合contain把影響限制在主要內(nèi)容區(qū)才把這一下優(yōu)化掉。說(shuō)到底Forced reflow 這條警告的價(jià)值不在于它本身而在于它是一個(gè)信號(hào)——它告訴你你的代碼正在用一種命令式、逐步確認(rèn)的方式跟瀏覽器打交道而瀏覽器更希望你一次說(shuō)清楚。把讀和寫分開(kāi)、把動(dòng)位置交給transform、把高頻事件壓到每幀一次這三件事做到位控制臺(tái)里那串紅色的[Violation]基本就會(huì)消失頁(yè)面手感也會(huì)跟著變一個(gè)檔次。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美日韩国产三级黄色| 91福利网在线观看| 91 刺激在线| 久久久久久69国产一区二区| 精品传媒在线一区| 亚洲情色一区二区三区| 欧美亚性天堂| 亚洲AV永久无码一区仙野| 亚洲日韩国产精品| www.91视频网| 懂色av中文字幕一区二区三区天美 | 超碰精品国产无码| 天天日夜干| 动漫av中文| 日韩一级二级| 91色婷婷综合久久中文字幕二区| 色性综合| 狠狠爱综合网| 亚洲综合精品国产一区| 欧美色视频在线| 麻豆国产精品午夜视频| 在线视频97| 男女国产精品| 亚洲人成网站7777| 亚洲午夜未满十八勿入网站日本又色又爽又黄 | 97久久免费| 97超碰美国| 97av在线视频| 国产综合久久久鬼色| 亚洲第一页色| 污到发麻的视频 国产| 亚洲精品成人激情在线| 成人欧美一区二区三区黑人一| 性开放中文AV高清无码免费看| 中文字幕日韩专区精品系列| 国产精品黄色三级av| 爽极品影院| 国产精品直播在线观看直播| 天天视频网站黄| 人人操我人人干| 中字幕人妻一区二区三区| 另类天堂| 欧美性生活男人的天堂| 97国产高清视频在线观看| 福利操逼| 高清无码国产亚洲| 精品精品精品| av婷婷色网| 丝袜狠狠草尤物人妻av91| 91neishe| 久久精品视频一区三区小泽玛利亚| 东北女人| 爱丝福利| a片自拍直播视频| 日韩成人私密一级精品av| 日本久久女同性恋视频| 岛国福利在线精品播放| aaaa少妇高潮大片| 桃色五月天| 亚洲综合113页| 欧美韩国你懂得在线| 91欧美巨乳| 91痴汉| 日韩无码一区二区三区| 男女日B国产| 欧美日韩在线国产在线| 91九久| 亚洲情色在线| 91成人精品| 国产精品点击进入在线影院高清| 精品成人亚洲午夜电影| 色99在线| 国产精品不卡一区二区三区| 中文乱码字字幕在线第5页| 久久中文字幕一区不卡| 久久一二三四五六七八九区区区 | 六月色婷婷| 黄色不卡视频| 宅男91视频在线播放| 新91视频.cmp| 这里是精品| 日日干男人的天堂| 91熟女网| 国产精品无码av在线 | 一区二区三区精品久久| 亚洲中文制服诱惑| 免费男人的天堂| 加勒比中文av| 一区二区三区四区免费视频| 欧美三级一级| 欧美韩日精品99综合| 日韩精品资源专区二区| 日本不卡三级网在线播放| 色欧洲97| 18啪啪手机免费性爱| 操逼日韩无码| 九七毛片九九毛片| 视频黄色国产一级| 蘋果手機免費看成人Av| 国产 日韩 欧美 中文 另类,国产 欧美 另类 制服 变态,高清 日韩 欧美 中文,高 | 日韩性爱网址| 另类专区加勒比| 69一区二区| 亚乱色| 亚洲日韩久久精品一区| 91伊人久| 国精综合一二三区影视| 日韩视频中文字幕| 久久国产精品一级二级三级| 97人妻人人躁人人玩人人| 大香蕉亚洲中文| 欧洲大香蕉| 岛国黄片网站| 2017天天透天天通天天擦| A级国产欧美激情在线| 伊人成人中文字幕久久网| 亚洲精品不卡一二三区| 密乳AV免费观看| 亚州色国| 亚洲图片色图欧美另类| 久噜噜| 中国少妇XXXX做受| 欧洲自拍色图gif在线| 人人人摸人人| 999熟女精品| 巨爆乳一区二区爆乳区| 日韩资源网| CCYY草草影院地址入口| 夜夜高潮夜夜爽| 91亚洲综合| 久悠悠av| 色在线综合| 色天堂综合| 午夜a成v人电影| 麻豆亚洲Av成人无码一区精品| 男女啊啊啊啊啊| 五月丁香色综合| 国产97在线 | 亚洲| 久久婷婷色| 日本幼女18+| 综合色久欲| 色嗨嗨在线| 精品夜夜澡人妻无码AV| 久久久一区二区三区四曲免费听| 亚洲AV无码乱码| 日韩AV中文字幕电影| 人妻三级在线中文字幕| 区一二区日韩亚洲乱码av电影| 三级日本一区二区三区| 青青草久草AV| 99这里有精品| 中文字幕AV乱伦| 另类欧美| 亚洲有薄码区日本系列中文字幕| 婷婷av在线中文字幕| 蜜臀久久久| www.色婷婷| 亚洲码在线中文在线观看| 久久av色| 日韩av影片在线观看| 久久老熟女| 偷拍欧美激情| 亚洲福利中文字幕在线| 国产多人在线观看视频| 久热这里| 大香蕉在线SuP| 五月激情视频| 天天操夜夜嗨| 超碰97人妻| 91国产伊人大香蕉| 熟妇熟女一区二三区| 日本视频在线观看污污污| 天天噜| 熟女高潮合集-永久久久-成人AV | 久久五月婷| 欧美日韩大香蕉| 国产精品白丝AV| 99操| 天天操女人| 欧亚免费视频| 小视频玖玖| 亚洲色阁| 夜夜高潮夜夜爽夜夜爱爱一区| 又摸又舔在线观看网站| 91在线|亚| 很黄很色的视频在线观看| 97精品一区二区三区免费| 久久噜| 欧美日本久久精品一区| 99青草| 桃花色涩综合影院| 强歼乱伦资源网| ,成人免费啪啪视频| 91丝袜人妻| 婷婷另类小说| 久久av色| 欧美少妇性乱| 97色视频在线| 粉嫩小泬久久久一区二区| 超碰在线974| 密桃99999| renqi久久久久久久久久久久| 中文字幕精品一区二区精| 粉嫩av平台| 日本色色色网站免费看不卡| 伊人麻豆传媒| 国产路线专区| 亚洲风情在线观看| 啊啊啊久久| 97美日韩视频| 久久久久久久| 国产精品国产精品国产| 国产一区二区成人av在线播放| 欧美牲| 美女啊啊啊啊啊啊| 欧美传媒| 尤物黄色在线观看网站| 九热视频| 日本不卡码黄色| 伊人久久大香线综合无码| 国产精品色哟哟| 97国产天堂岛| 亚洲极品| 97在线免费观看视频| 91日韩| 日韩免费在线观看不卡| 制度丝袜99| 91足交| HEYZO高无码国产精品227| 亚洲精品啪视频| 日本中文字幕在线视频| 熟女丰满人妻一区| 欧美亚洲宗合色性图| 夜夜爽夜夜摸夜夜操免费视频| 日本不卡免费二区| 久久精品—区二区三区内射| 俄罗斯一区二区视频在线观看| 欧美性生活免费网| 久久,精品一二三| 久九干| 国产亚洲日本| 99国产女人| 国产又黄又爽| 国产人伦a片信息免费片| 日本色色色视频| 五月激情天| 夜夜夜夜夜夜夜夜夜狠狠狠狠狠狠狠| 亚洲精品一卡二卡三卡福利视频网站| 肥佬影院91| 精品无码一区二区三区色欲| 亚洲强奸乱伦影视网| 亚洲高潮少妇| 亚洲综合色在线| 精品国产乱码久久久| 思思视频免费看网站| 成人网站 免费观看| 99ri在线视频| 国产免费久久精品99re韩国| 日韩91网站| 91午夜无码| 99久久99久久综合| 91爱看| 97天天摸天天爽| 日本午夜精品理论片A级APP发布| 一及黄久一点| 夜夜躁狠狠躁日日躁av| 99热99在线播放激情| 96AV精品| 欧美在线电影| 国产农村一一级特黄毛片| 国产精品网站免费| 女人久久久| 久久久久国产精品片区无码直播 | 亚洲熟女乱色一区二区三区| 清柠毛片| 天堂性色| 色播丁香| 男人的天堂kva| 欧美性生活免费网| 91色综合激情| 日韩福利电影网| 丁香五月大香蕉| 久偷拍欧美日韩三区| 五月天我淫我色av| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 日韩在线国产字幕| 亚洲天堂区| 亚洲 欧美 日韩另类 麻豆| 国内亚洲精彩视频在线| 久久精品老司| 日日操免费视频| 精品久久在线区一区| 鸥美中出| 日本91白丝| 亚洲欧美情色| 欧美狠狠弄| 干我久操| 青青草中日韩在线| 国产99 中文字幕日韩小视频| 呦女网站| 97干在线视频| 国产精品乱码久久久久| 麻豆天美久久91| 日韩色| 欧美亚涩| 超碰免费人妻人人| 欲香欲色天天天综合和网| 久久久久久国产成人| 欧美精品91| 天天爽夜夜爽夜夜爽精| 学生妹天天看| 啊啊啊操一区| 免费αV在线视频| 91中文精品日韩欧美在线| 日韩无码三级影院| 人人操人人精品影片| 91久久久久久久久18| 亚洲欧美骚| 亚洲色图激情小说| 亚洲一级性爱视频免费看| 91国产在线精品| 人人透人人操| 欧美片第一页| 婷婷九月丁香| 香蕉一区二区三区在线视频| 日韩精品国产一区二区| 在线色资源| 色婷婷六月| 免费人成毛片乱码| 精品综合久久久久久97| 女人妻一区| 思思热久久成人| 中日韩久久久免费看| 五月天综合网| 久操网视频| 嗯嗯啊啊啊好爽| 久久e6只有精品| 国产精品视频一区二区三区八戒| 91 综合网| 久久国产视频专区一二三| 精品国产人成在线| 91伊人| 丝袜视频一区二区在线播放国产中文| 影音先锋国产精品| 岛国AB视频| ji熟女.com| 久区视频| 天天综合网亚洲综合网| 综合网亚| 欧美内射少妇| 人妻久久久久久| 午夜乱轮操逼视频免费看| 91视频女生| 91美女视频在线| AV九九| 亚洲一级性爱视频免费看| 伊人九九九| 激情啪啪视频| 五十路人妻在线| 乱日视频| 午夜人妻精品综合在线| 啪一啪免费视频| 五月丁香六月综合缴清无码 | 91亚洲网| 蜜臀久久99精品久久久久久酒店| AV色图| 久草精品国产蜜臀| 嗯嗯嗯啊啊啊在线免费观看| 日本污ww视频网站| 大伊香蕉在线视频免费| 上海一级黄片| 操操操日本的逼| 国内精品a| 久久天天艹| AV乱伦专区| 国产一国产一级毛片古装| 91久热| 操老熟女AV| 日韩大香蕉精品在线视频| 嗯嗯,好大,好爽,好骚| 欧美少妇一区二区三区| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 久久精品人人做人人看| 欧美18老人禁| av网站国产主播在线| 男人的天堂网页| 色五月av| 家庭乱伦麻豆| 亚洲AV成人无码一二三久久| 一本色道综合久久欧美| 欧美aa一级片| 亚洲超碰AV| 思思热免费视频观看| 久久香蕉综合一本到3atv| 国产超碰| 内射白嫩美女| 乱码熟妇人妻久久久| 97综合国产精品高潮久久| 九九九久千久久激情蜜桃在线看 | 91中出视频| 亚洲97超碰| 久操91视频| 婷婷av在线中文字幕| 日韩视频精品在线观看| 白天啪啪晚上啪啪视频| 在线观看综合精品亚洲| 欧美在线播放aaaa| 国产视频一区二区在线| 少妇人妻无码| 91激情国产| 漂亮人妻被强中文字幕hd| 免费视频观看60秒| 国产精品国产亚洲区艳妇糸列| 91啦人妻| 色色色色电影网| 天天干美少妇一区| 啊啊啊不要啊啊受不了了视频在线| 综合色拍| 日韩精品-原创伙伴| 亚洲无码精品AV久久久| www.久久最新地址| 大香蕉免费中文| 欧美A√综合网| 91热色| 很很操在线| 91人妻做a观看视频| 操一区| 69精品人人人人| 久久久久久久久9| 一级做受视频免费是看美女| 大香蕉av在线| 久久一本大香蕉| 日夜伊人网| 日韩激情啪啪啪| 色欧美天天| 亚洲国产中文字幕| 国产精品久久久吖| 久久久一区二区三区四曲免费听| 亚洲综合贴图91| 色婷婷一区二区三区久久| 日欧亚洲二三区大片不卡| 久久久久13| 国产精品乱码久久久、久久| 日韩欧美亚洲自拍偷拍| 99九九久久| 精品一区二区三区四区外站| 亚洲**2021在线观看| 国产亚洲综合欧美一区| 色哟哟av网址| 国产熟女完整版中字| 性色avv| 三及片网站| 懂色AV蜜臀无码精品APP| 动漫片子网站3黄| 亚洲男人天堂手机版| 青草青草久热| 午夜精品久久久99热蜜桃的功能特点| 一级特黄aaa大片在线观看成人一级片在线观看 | 日本中文字幕高跟| 亚洲性天堂| 亚洲 国产 精品一区| 男人的天堂.com| 丰满人妻av一区二区三区| 福利风月五月天影院| 中文字幕丝袜| 伊人久久婷婷| 安微少妇操BBB| 精品人妻一区二区视频| 久久精品夜色国产亚洲AV| 日韩三级伦理中文字幕| 97视频观看| 夜夜骑夜夜操| 97超碰色屌| 亚洲国产精品无码AV久久| 日本免费中文一区二区三区四区| 天天亚洲| 欧美日日夜夜| 国产不良强奸视频免费看| 亚洲情色1区| 亚洲一区二区三区春色| 天天享受天天看| 日韩精品国产一区二区| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 国产精品 久久久精品一牛| 亚洲色图 欧美热图 清纯唯美 另类自拍 | 性爱1区| 清纯唯美激情| 精品国产乱码久久久久久久久1| v91av| 成人AV素股で擦久久| 国产强奸乱伦欧美| 岛国人妻少妇av在线观看| 国产特级毛片AAAAAA高潮流水 | 一牛一区二区三区久久| 精品国产人成在线| 色欧美在线| 狠狠狠一区二区三区| 18禁看网站一区| 色综和网| 丁香五月激情啪啪| 久热在线精品免费观看| 久久久9 9 9精品| 农村妇女一级二级三级视频| 国产精品久久久久无码Av网曝门| 欧美 亚洲 综合 制服 另类| 丰满人妻一区二区三区免费,| 午夜性生活av免费在线看| AV丝袜东京热| 玖色AV| 黄色电影观看久久9| 天天日天天干天天摸天天操| 美女97超碰| 人妻精品视频一区二区| 欧美人人操人人插| 少妇激情一区二区三区视频| 热久日综合| 大香蕉五月天| 国产一进一出视频网站| 精品一级毛片在线观看| 久久久九九| 一区,二区,三区网站| 欧美久久伊人| 强奸乱伦AV网址| 97se亚洲综合自| 热热色色综合| 鸥美插入视频| 天天操av懂色| 伊人久久婷婷| 熟女人妻一区二区三区| 国产日韩在线播放av| 蜜臀久久99精品久久久久久婷婷 | 国产无码一二三区| www.yeyecao| 欧美97超碰| 丰满少妇精品一区二区| 91国产美女丝袜足交精品视频 | 国产久久久久久| 欧美激情精品久久久| 精品国产一区二区三区久久久蜜臀 | 国产综合网站在线播放| 欧美日韩黄片精品在线| 亚洲av青草久久一区二区| 青青草在线视频播放器| 亚洲情色 无码专区| 色大香蕉97N| 欧美性区| 物尤视频一区二区| AV天堂男人的天堂| 67194无码不卡| 一区二区偷拍拍视频| 99热99色| 色情五月婷婷| 婷婷久久五月| 色色色999| 日本道久久综合色色| 国产91精品福利在线| 国产一区二区三区白丝| 国产精品久久久久久高清无码免费看| 欧美国产精品久久九九| 亚欧高清| 乱伦一区二区三区‘| 无码外流操逼视频| 强奸国产在线| 日本操BAV| 免费看日产一区二区三区| 欧美人妻一区| 国产成人+综合亚洲+天堂| 国产欧美一区激情交| 二色av| 少妇高潮99p| 91老熟女逼| 精品十三区| 亚洲 另类 丝袜 自拍 动漫| 欧美日韩中国x| 91高清欧美| 加勒比海色香蕉婷婷| 最新日本中文字幕| 一级性爱啪啪视频| 精品一区二区成人动漫| 丰满人妻一区二区三区免费,| 女色视频社区| 天天天天天天天天综合| 欧美女同在线| 欧美激情激情xxxx欧美专区| 欧美一级黄片视频在线| 久久精品亚洲成a人天堂| 9久精品| 熟妇视频一区二区三区在线观看| 最新精品久久蜜桃 | 99热这里只有是精品10| 久久久涩| 91被操| 亚洲AV成人无码久久精品播放| 狠狠操狠狠| 欧美日韩222| 麻豆区久久久久亚| 日韩无码人妻| 强奸乱伦av电影| 91久精品| 亚洲色天堂九9| 网站A V在线| 五月天黄色激情视频| 亚洲春色激情小说| 久久偷偷色综合蜜桃| 天天肏天天干| 成人三级片无码| 日本午夜福利视频| 操久久久久| 超碰成人公开| 大香蕉伊人网WWWn0n| 天天日骚逼熟女| 蜜臀AV秘一区翔田千里| 色婷五月天| 色香伊人| 精品日韩人妻精品一二三区| 天天综合网站| 好爽要喷了| 日本成人A片网站| 人妻啊啊人妻啊| 欧美黑人日韩少妇色情| 日韩99精品视频综合区| ′ !γ}丶。。久久精品欧美一区二区三区| 人妻少妇精品久久久| 欧美激情激情xxxx欧美专区| 天天爱天天操| 伊人9| 久久精品高清AV| 看黑丝美女操逼青青网站| 色九久| www.91久久| 婷婷九月国产| 欧洲成人性爱视频| 夜夜人妻爽| 秋霞一级鲁丝片A片| 日本三级久| 91亚洲图片| 色综合色色| 欧美97av| 婷婷色色网| 亚洲图片欧美偷拍| 色婷婷五月综合| 99热在线只有精品| 国产福利精品最新在线| 91模特在线观看| 免费啪啪啪网站18岁| 中文字幕精品专区搜索结果91| 久久亚洲AV无码专区首页| 久久久久密臀视频| 啪啪资源网| 超碰伊人在线| 日韩一级欧美一级在线观看| 久久精品无码不卡| 丁香婷婷九月| 日本精品一区二区不卡| 青青草中文-久久青草精品一区二区三| 中文字幕精品专区搜索结果91| 激情网色| 新怡红院| 韩国一区二区精品亚洲| 久久精品一区二区一8| av在线人气| 一本色道综合久久欧美| 亚洲在高跟鞋自慰久久在色线| 天天色黄色影院天天操| 丰满人妻一区二区中文| 九九RE视频在线精品| 夜夜欢天天干| 婷婷激情一区二区三区俺也去| 日本人妻中文字幕| 风月影院男女十八禁| 亚洲国产无码精品首页久久久| 五月天久久人妻| 67914亚洲精品| 欧美性爽xyxOOOO| 99re99视频在线免费观看| 午夜欧美女人操逼| 69一区二区三区 | 美女熟妇色| 亚洲久久东京热一二三四五区视频| 欧美成人午夜免费福利785| 天天爱天天操| 国产精品密臀网在线观看| 蜜乳AV色欲AVAV无码| 欧美精品97| 蜜桃视频一区二区三区 | 天天色综合影视网| 国内精品久久国产,www香蕉久久五月丁香,亚洲欧美日韩精品永久在线,日本精品一 | 老熟妇一区二区三区啪啪| 日韩一级片在线看| 亚洲日韩av专区无码| 日韩色图 一区二区| 国模限制级电影| 国产精品婬乱一级毛片彝族| 酒色综合网| 97超碰在线资源网站| 另类小说五月天| 欧亚性爱在线视频| 国产伦精品| 久久精品中文字幕女同| 97亚洲性爱| 爽 好舒服 无码刺激久久| 亚洲影院成人| 中国和日本人色哪个不下载能放| 日韩亚洲欧美中文字幕| 天美传媒Av在线| 理论久久婷婷网 8| 一区三区啪啪| 久综合国内精品自在自线| 亚州男人天堂| 97在线观看免费| 日日夜夜噜| 99999久久久久9国产精品| 最新日韩黄片| 秋霞无码av鲁丝片一区| 国产真乱mangent| 蜜臀久久99精品久久久久久婷婷| 亚洲色图第四色| 99RE在线视频精品,这里只有精品| 五月激情小说| 色小视频蜜乳| 操我无码| 亚洲AV无码AV吞精久久久久| 日韩偷拍一区二区三区| 少妇综合网| 国色综合天| 色原狠狠天天天| 免费国产| 无码精品啪啪啪一区二区三区三州| 久久久婷婷| 亚洲综合113页| 久久色一区| 国产精品91一样| 亚洲欲色9532548967一区| A久久| 精品人妻伦一二三区久久| 激情久久av一区av二区av| 91 亚洲 欧美 日韩 国产 综合| 日本狂喷奶水在线播放212| 九九精品无码专区免费| AV天堂国产| 强奸乱伦AV网址| 久久性爱精品一区| 亚洲 欧美 偷拍 唯美| 少妇啪啪自拍| 国产尤物AV尤物在线观看不卡| 国产女人极品高潮毛片| 日韩色欲久久一二三四区| 可能人人看人人摸| 欧美成人一级免费电影| 久久免费精品视频免一| 国产亚洲日本精品在线| 国产乱伦一二三区| 五月婷在线| 91N欧美| 蜜桃中文字日产乱幕4区| 极品粉嫩一区二区| 秋霞午夜视频一区二区| 经典丝袜一区| 无码二级三级| 啪啪综合网| 中文字幕一区二区免费在线| 久久久无码av精| 天天综合精品| 91色黑人少妇| 精品人妻一二三四区视频| 91插B网站| 亚洲欧美情色| 变态乱伦伪娘灌肠一区二区| 日韩激情啪啪| 欧美性天天影视| 亚洲情色一区二区三区| 亚州黄站| 日本熟女不卡视频| 欧美成人一区二区三区在线播放| av九九| 18岁禁 茉莉成人久久| 99国产精品自在自在| 亚州综| 国产51色综合久久免费| 97人人超| 91黑丝美女| 久久精品无码一区二区三区| A片大香蕉在线| 自拍偷拍2025在线观看| 富二代亚洲精品99 | 国产激情av女片自拍| 日韩一区二区精品视频| 久久久久ab| 啊啊啊久久| 无码精品人妻一区二区三区妖精| 亚洲免费看片| 久久伦理视频久久大香蕉视频| 熟女熟妇一区二区三四区| 韩三级a视频在线观看| 久久婷婷视频| 一本久久精品中文字| 啊啊嗯嗯好爽| 最新国产亚洲精品精品国产亚洲综合| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 夜夜高潮夜夜爽高清视频一| 亚洲亚洲亚洲天堂天堂| 久久无码一区二区二三区性色| 99九九久久| 久草精品视频| 69av一区二区三区| 一区二区你上我| 欧美三四五区| 久久人人爽爽人人爽人人片αV| 精品精品精品| 亚洲色图欧美色18直播在线| 国产一级特黄大片处女| 久久久久久中文字幕中文字幕最新| 夫妻AV网站| 密乳无码| 中 文字幕一区二区三四 五 区日 日 骚 | 无遮挡男女激烈动态图| 屌色在线97视频| 亚洲中文sv| 丰满人妻av一区二区三区| 亚洲综合情色| 久久精品中文字幕观看| 日韩懂色网| 综合影院永久入口国产| 欧美日韩99精品麻豆传媒| 9I1性色影院| 国产又粗又长又爽又色| 999 久久久| 被男人添B超爽视频| 91jk色拍| 欧美的性爱网站免费| 人人操天天爽| 1769一区| 少妇人妻无码| 国产在线强奸视频| 国模不卡一本二本三电影| 欧美人人操人人插| 四虎884a| 国产精品干干干| 91少妇通奸网站| 激情啪啪拍91| 一本色道熟妇| 视频二区美腿丝袜制服人妻欧美| 欧美色图第一页| 九色 人妻 大香蕉| 午夜人人操| 国产成人主播| 亚洲色图日韩精品| 97中文综合| 天天日天天舔天天喷天天射| 欧美精品97| 丝袜性亚洲| 免费的很黄很污的全部视频 | 色玖玖| 一区二区乱码福利| 极品粉嫩少妇视频| 乱伦3P视频| 久操免费观看| 欧美高清性猛交| 神马久久久久久伦理片| 伊人久日| 国产女上位好爽在线| 偷拍 欧美 日韩| 天天澡天天爽日日av| 欧日a| 亚洲国产精品无石码久久| 泰国AV在线观看| 精品成人动漫一区二区| 亚洲一区二区中文字幕| 宅男91视频在线播放| 欧美不卡二区| 亚洲乱妇p22| 国产天天看| 欧美日韩国产色图在线| 欧美日韩中文视频播放| 91在线丝袜视频| 久久99精品视频| 在线人成亚洲视频免费观看| 后入福利| 九九成人精品| 久热婷婷| 在线无码网站| 美女91| 99后入| 桃色六月天| 国产三级电影免费观看| 日韩免费簧片| 亚洲干B| 日韩欧美丝袜诱惑| 综合熟女| 手机在线视频国内精品| 97亚洲综合| 免费男人的天堂| 国产精品久久久久久久久久久久久久久久久久| 欧美成人一区二区三区在线播放| 日韩成人无码| 中文字幕一区二区三区人妻不卡| A啊啊在线观看| 最新欧洲欧美日本激情网站| 国产亚洲精品av一区| 一区二区三区国产在线播放| 成人草草视频| 天天操人人操骚逼网站| 九九毛片这里只有精品| 一级免费啪啪片| 可能人人看人人摸| www.99色| 三久久久四久久久久| 欧美日韩人妻精品一区二区三区| 97久久精品国产| 人妻夜夜爽天天爽麻豆三区网站| 久久久精品国产亚洲AV无码| 欧美另类精品xxxx| 日韩免费福利在线观看| 91美女视频在线观看| 在线观看啊啊啊啊啊| 欧洲自拍色图gif在线| 亚洲色图欧美色图制服丝袜| 日韩乱码av| a久久| 婷婷99| 乱老女人一区二区视频| 囯产操逼片| 久久毛卡| 色噜噜精品一区二区三| 亚洲精品尤物yw在线影院| 国产乱伦视频污| 上特色A在线| 欧美性91| 69精品| 国产精品久久久久久久久久久久| 久操国产在线| 久久久久久九| 玖草在线视频| 婷婷久久五月综合激情| 日本人妻最新在线中| 极品另类| 精品综合久久久久久五月天| 大学生美女口爆| 欧州一区二区三区四区| 1000部熟女视频在线观看| 国产91亚洲精品一区二区三区| 亚洲成人激情小说视频| 人人爱人人乐人人操| 人人看黄色视频| 性久久久| 国产不卡免费在线视频| 亚洲最大无码中文字幕网站| 欧美性爱在线无码| 91一区二区| 超碰调教97| 亚洲欧洲精品成人| 在线亚洲丝袜视频网站| 午夜精品人妻二区三区| 少妇九九九九| 综合久久9| 无码高清操逼网址| 国产亚洲美日韩Aⅴ中文字幕无码成人| 一牛影视成人片免费| av天堂手机版追回| 激情综合五月天| 熟妇人妻一区二区| 日韩精品大香蕉伊人在线| 拍拍拍拍大尺度黄色三级片拍拍拍拍拍照| 欧美日韩系列| 精品高潮| 日本操逼视频导航| 日本99热| 日本一区99| 天天在线91| 又粗又长又大国产不卡| 亚洲免费成人在线高清无码视频| 日本操BAV| av优播| 青青伊人这里只有精品| 一区二区视频在看| 国产一区二区三区白丝| 国产在线精品偷| 亚洲人精品久久久喷水| 色在线69堂| 久草加勒比一区在线| 日日日日做夜夜夜夜无码| 99操视频| 久久久久久久国产| 超碰色图| 久久美女国产| 亚洲综合97中文网| 亚洲精品白丝| 在线日韩精品一区二区三区| 成年人一级黄色毛片大全在线观看| 九九九九久久久| 少妇精品久久久| 啊啊嗯嗯好爽| 成人日本视频人妻在线| 亚洲激情 欧美色图| 蜜桃天美传媒AV一区二区三区| 国产成人拍国产亚洲精品| 中文字幕黄色片| 久草男人天堂| 男啪女色黄无遮挡免费观看| 插欧洲美女欧美精品| 91性生活久久久| 夜夜欢天天干| 女人被添高潮免费视频| 一区| 日本成人免费一区二区三区| 色综合久久久久| 精品少妇人妻| 免费视频在线一区二区不卡| 长长久久免费视频| 伊人久大| av在线免费一区二区| 欧美 青青草| 风月影院十八禁| 日本久久99| 国产黑白丝在线| 国产亚洲精品农村妇女| 欧美一二在线| 91人妻人人澡人人爽人人精品| 婷婷导航| 婷婷8月天青娱乐| 国产自偷自拍一区| 日日干夜夜欢| 国产一区二区a毛片| 国产午夜福利视频在线| 亚洲无992tv| 国产高清1234区| 色逼综合| 久久婷婷一区二| 久久岛国| 无码又爽又硬又激情免费视频| 91美女视频。| 亚洲AV永久无码一区仙野| 99这里都是精品| 一区三区啪啪| 热热色青青草| 婷婷亚洲综合| 就去色综合| 桃色五月天| 嗯嗯啊好爽| 欧美大码在线视频| 熟妇综合一区二区三区| 蜜桃久久久久久久| 日本精品中文字幕视频| 天美一二三在线观看Av| 国内精品嫩模A∨私拍小视频| 九九九综合精品| 尹人免费观看视频在线| 久久久久久久国产| 日韩性爱视频在线免费观看| 97AV在线免费观看| 91三级理论片播放器| 久久r精品| 日本三级大片| 日日夜夜精品视频| 开心六月色| 国产精品干干干| 天天综合站| 99这里只有精品| 国产免费黄色一级大片| 亚洲视频小说| 高跟丝袜AV专区国产| 日本久久久久久久久久| 国产久久一区二区午夜| 国产日韩精品suv| 欧美色图人妻| 九热视频| 免费AV中文网在线观看| 性性久久| 91狠狠综合久久| 欧美精品久久96人妻无码| 国产成自自拍在线观看| 日韩精品黄片免费观看| 国色综合天| 久久AV无码1区2区3区| 操逼啊啊啊91| 搡老女人老熟女91老熟女综合网| 中文乱码99| 日本午夜久久电影| 亚洲阿v天堂在线| 伊人久久亚洲色欲综合网站| 熟妇在线视频一区二区| 国产高清吃奶免费视频网站| 不卡六六在线91| 精品网站9999| 欧美午夜一区二区三区| 午夜精品久久久久久久久久久久久| 国产精品午夜成人福利| 在线观看黄色电话| 高清有码一区二区| 自拍第一页| 欧美少妇第一页| 久久久18| 国产精品女生av| 日韩啪啪视频| 97精品在线| 九一亚洲国产免费| 免费的黄片wwwwww| 国产午夜福利电影免费在线观看| 欧美性少妇| 黄色不卡视频| 极品丝袜无码| 999岛国大片| 国产毛片在线| 2024黄色视频| 91制服丝袜| 久久九操在线观看| 少妇国产不卡| 婷婷五月色| 国产激情在线| 99精品欧美一区二区三区桃色| 久久一区二区三区四区五区| 香蕉大久久久| 欧美性爱一区| 久久精品视频久久久| 丁香九月激情| 成人性爱美曰韩| 免费啪啪av| 四虎精品永久在线播放| 9I1性色影院| 青青草国产一区二区三区| 啊啊啊97视频| 国产精品熟女AV中文字幕在线播放| 久久婷婷色| 在线观看日韩av不卡| 伊人久久在线视频观看| 国产精品久久aV| 精品免费一区| 97精品免费视频网站| 91情色在线| 偷偷人人精品女女久久| 国产中午字一暮区| 色拍偷亚洲| 青木玲在线不卡| 超碰1997| 久热久操| 中文字幕视频免费| 日本天天干天天搞一区| 伊人久久大香线综合无码| 最新一二三区视频| 好屌色综合| 18禁网站在线播放| 欧美v亚洲v综合v国产v妖精| 久久久久久999| 久久久偷拍| 国产美女自拍视频| 欧美九九九| 国内精品99999| 亚州欧美在线| 超碰碰97资源站| 欧美性夜| 九九久久久| 欧美亚洲小说| 探花精品 一区二区| 亚洲情色欧美| 久久精品国产精品一区| 99婷婷一区二区| 久久av无码| 精品人妻1区| 91人妻中文| 搡老熟女老女人老熟妇免费视频|