摘要:如下圖所示渲染性能保證主動(dòng)交互讓用戶感覺(jué)流暢一般超過(guò)認(rèn)為是長(zhǎng)任務(wù)會(huì)阻塞的運(yùn)行如下是兩種解決方案。下面是另外一種使頁(yè)面流暢的方法時(shí)間分片。
流暢性
本篇是基于 FDCon2019 上《讓你的網(wǎng)頁(yè)更絲滑by劉博文》的復(fù)盤文。該課題也是博主感興趣的領(lǐng)域, 后續(xù)會(huì)結(jié)合 React 的 Schedule 與該文進(jìn)行進(jìn)一步整合, 個(gè)人博客
被動(dòng)交互: animation
主動(dòng)交互: 鼠標(biāo)、鍵盤
被動(dòng)交互當(dāng)前市面上的設(shè)備頻率在 60 HZ 以上。
主動(dòng)交互跑如下界面 https://code.h5jun.com/pojob
結(jié)合如下代碼塊, 可以看到 100ms 以下的點(diǎn)擊是順暢的, 而超過(guò) 100ms 的點(diǎn)擊就會(huì)有卡頓現(xiàn)象。
var observer = new PerformanceObserver(function(list) { var perfEntries = list.getEntries() console.log(perfEntries) }); observer.observe({entryTypes: ["longtask"]});讓用戶感覺(jué)到流暢
衡量一個(gè)網(wǎng)頁(yè)/App 是否流暢有個(gè)比較好用的 Rail 模型, 它大概有以下幾個(gè)評(píng)判標(biāo)準(zhǔn)值。
Response —— 100ms Animation —— 16.7ms Idle —— 50ms Load —— 1000ms像素管道
像素管道一般由 5 個(gè)部分組成。JavaScript、樣式、布局、繪制、合成。如下圖所示:
渲染性能保證主動(dòng)交互讓用戶感覺(jué)流暢
function App() { useEffect(() => { setTimeout(_ => { const start = performance.now() while (performance.now() - start < 1000) { } console.log("done!") }, 5000) }) return ( ); }
一般超過(guò) 50 ms 認(rèn)為是 long task(長(zhǎng)任務(wù)), long task 會(huì)阻塞 main thread 的運(yùn)行, 如下是兩種解決方案。
Web Workerapp.js 代碼如下:
import React, {useEffect} from "react" import WorkerCode from "./worker" function App() { useEffect(() => { const testWorker = new Worker(WorkerCode) setTimeout(() => { testWorker.postMessage({}) testWorker.onmessage = function(ev) { console.log(ev.data) } }, 5000) }) return ( ); }
worker.js 代碼如下:
const workerCode = () => { self.onmessage = function() { const start = performance.now() while (performance.now() - start < 1000) { } postMessage("done!") } }
此時(shí)在輸入框輸入時(shí)沒(méi)有卡頓的感覺(jué)。
Time Slicing下面是另外一種使頁(yè)面流暢的方法 —— Time Slicing(時(shí)間分片)。
觀察 Chrome 的 Performance, 火焰圖如下,
從火焰圖可以看出主線程被拆分為了多個(gè)時(shí)間分片, 所以不會(huì)造成卡頓。時(shí)間分片的代碼片段如下所示:
function timeSlicing(gen) { if (typeof gen === "function") gen = gen() if (!gen || typeof gen.next !== "function") return (function next() { const res = gen.next() // ① if (res.done) return // ⑤ setTimeout(next) // ③ })() } // 調(diào)用時(shí)間分片函數(shù) timeSlicing(function* () { const start = performance.now() while (performance.now() - start < 1000) { console.log("執(zhí)行邏輯") yield // ② } console.log("done") // ④ })
該函數(shù)雖然代碼量不長(zhǎng), 但卻不易理解。前置知識(shí) Generator
下面對(duì)該函數(shù)進(jìn)行分析:
往時(shí)間分片函數(shù) timeSlicing 中傳入 generator 函數(shù);
函數(shù)的執(zhí)行順序 —— ①、②、③、① (此時(shí)有個(gè)競(jìng)賽的關(guān)系, 如果 performance.now() - start < 1000 則繼續(xù) ②、③, 如果 performance.now() - start >= 1000 則跳出循環(huán)執(zhí)行 ④、⑤);
conclusion針對(duì) long task 會(huì)阻塞 main thread 的運(yùn)行的情形, 給出兩種解決方案:
Web Worker: 使用 Web Worker 提供的多線程環(huán)境來(lái)處理 long task;
Time Slicing: 將主線程上的 long task 進(jìn)行時(shí)間分片;
保證被動(dòng)交互讓用戶感覺(jué)流暢保證 16.7ms 有新的一幀傳輸?shù)浇缑嫔稀3ビ脩舻倪壿嫶a, 一幀內(nèi)留給瀏覽器整合的時(shí)間大概只有 6ms 左右, 回到像素管道上來(lái), 我們可以從這幾方面進(jìn)行優(yōu)化:
避免 CSS 選擇器嵌套過(guò)深Style 這部分的優(yōu)化在 css 樣式選擇器的使用, css 選擇器使用的層級(jí)越多, 耗費(fèi)的時(shí)間越多。以下是測(cè)試 css 選擇器不同層級(jí)篩選相同元素的一次測(cè)試結(jié)果。
div.box:not(:empty):last-of-type span 2.25ms index.html:85 .box--last span 0.28ms index.html:85 .box:nth-last-child(-n+1) span 2.51ms避免布局重排
// 先修改值 el.style.witdh = "100px" // 后取值 const width = el.offsetWidth
這段代碼有什么問(wèn)題呢?
可以看到它會(huì)造成布局重排。
應(yīng)對(duì)的策略是調(diào)整它們的執(zhí)行順序,
// 先取值 const width = el.offsetWidth // 后修改值 el.style.witdh = "100px"
可以看到經(jīng)過(guò)調(diào)換順序后, 后執(zhí)行的 el.style.width 會(huì)新開(kāi)一個(gè)像素管道, 而不會(huì)在原先的像素管道進(jìn)行重排。
此外不要在循環(huán)中執(zhí)行如下的操作,
for (var i = 0; i < 1000; i++) { const newWidth = container.offsetWidth; // ① boxes[i].style.width = newWidth + "px"; // ② }
可以在火焰圖中看到它發(fā)生了重繪的警告,
執(zhí)行順序是 ①②①②①②①..., 假若我們?cè)诘谝粋€(gè) ① 后面插入一條豎線后 ①|(zhì)②①②①②①, 其就變成先修改值后取值的情景, 所以也就發(fā)生了重繪!
正確的使用姿勢(shì)應(yīng)該如下:
const newWidth = container.offsetWidth; for (var i = 0; i < 1000; i++) { boxes[i].style.width = newWidth + "px"; }避免重繪
創(chuàng)建 Layers(圖層) 可以避免重繪,
{ transform: translateZ(0); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/109839.html
導(dǎo)語(yǔ)▼上篇講到產(chǎn)品的一致性是產(chǎn)品的金鑰匙,通過(guò)對(duì)一致性的設(shè)計(jì)可以使產(chǎn)品在品牌標(biāo)識(shí)、用戶使用和開(kāi)發(fā)效率等方面得到提升。交互設(shè)計(jì)對(duì)于產(chǎn)品有哪些價(jià)值呢?本質(zhì)是站在多維角度挖掘,分析,梳理,提煉用戶更深層?的?需求和痛點(diǎn)?,利用交互理論方法,保證產(chǎn)品的設(shè)計(jì)完整性,產(chǎn)品用戶體驗(yàn)的流暢性,產(chǎn)品商業(yè)價(jià)值的最大化。What|什么是交互設(shè)計(jì)?我們的日常生活中處處可見(jiàn)交互行為,從使用淘寶購(gòu)物到掃場(chǎng)所碼向防疫人員展示核...
摘要:騰訊瀏覽服務(wù)是致力于優(yōu)化移動(dòng)端體驗(yàn)的解決方案由瀏覽器團(tuán)隊(duì)出品使用騰訊瀏覽服務(wù)內(nèi)核和騰訊瀏覽服務(wù)云端服務(wù)解決移動(dòng)端使用過(guò)程中出現(xiàn)的拖拽不流暢切換留白窗口閃爍等問(wèn)題。 這是一個(gè)移動(dòng)互聯(lián)的時(shí)代,這是一個(gè)屬于Android,屬于iOS的時(shí)代,在響應(yīng)大眾創(chuàng)業(yè)萬(wàn)眾創(chuàng)新的號(hào)召下,越來(lái)越多的開(kāi)發(fā)者轉(zhuǎn)向了移動(dòng)開(kāi)發(fā)的領(lǐng)域。在Android,iOS剛剛興起的時(shí)候,對(duì)于開(kāi)發(fā)者而言,要開(kāi)發(fā)一整套完整的App是一...
摘要:如何挑選合適的導(dǎo)航結(jié)構(gòu)導(dǎo)航設(shè)計(jì)是應(yīng)用設(shè)計(jì)的關(guān)鍵,設(shè)計(jì)規(guī)范以下簡(jiǎn)稱規(guī)范中將導(dǎo)航元素分為對(duì)等層次和歷史導(dǎo)航等幾類,例如表和透視表導(dǎo)航窗格是對(duì)等導(dǎo)航元素,中心大綱細(xì)節(jié)屬于分層導(dǎo)航元素,返回則屬于歷史導(dǎo)航元素。 此文已由作者楊凱明授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問(wèn)網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營(yíng)經(jīng)驗(yàn)。 繼Windows 10系統(tǒng)發(fā)布之后,很多Windows用戶更新了系統(tǒng)。win10系統(tǒng)的發(fā)布,...
摘要:那該如何是好原題給出思路是讓事件負(fù)責(zé)標(biāo)記按鍵就好了,而方向鍵的事件處理使用設(shè)個(gè)周期比較小的定時(shí)器持續(xù)監(jiān)聽(tīng),由于周期小,長(zhǎng)按時(shí)就會(huì)立刻執(zhí)行相應(yīng)的事件處理,效果更加流暢。閃爍實(shí)現(xiàn)效果閃爍簡(jiǎn)單的一個(gè)定時(shí)器應(yīng)用,用或都可以實(shí)現(xiàn)。 0x1模擬select控件 實(shí)現(xiàn)效果:5-01模擬select控件 比較簡(jiǎn)單的點(diǎn)擊事件處理,也就處理點(diǎn)擊選擇框展示菜單、點(diǎn)擊菜單選擇、點(diǎn)擊頁(yè)面任意角落隱藏菜單這三件事...
摘要:端優(yōu)談?wù)勱P(guān)于前端的緩存的問(wèn)題我們都知道對(duì)頁(yè)面進(jìn)行緩存能夠有利于減少請(qǐng)求發(fā)送,從而達(dá)到對(duì)頁(yè)面的優(yōu)化。而作為一名有追求的前端,勢(shì)必要力所能及地優(yōu)化我們前端頁(yè)面的性能。這種方式主要解決了淺談前端中的過(guò)早優(yōu)化問(wèn)題過(guò)早優(yōu)化是萬(wàn)惡之源。 優(yōu)化向:?jiǎn)雾?yè)應(yīng)用多路由預(yù)渲染指南 Ajax 技術(shù)的出現(xiàn),讓我們的 Web 應(yīng)用能夠在不刷新的狀態(tài)下顯示不同頁(yè)面的內(nèi)容,這就是單頁(yè)應(yīng)用。在一個(gè)單頁(yè)應(yīng)用中,往往只有一...
閱讀 3402·2021-11-24 09:38
閱讀 3189·2021-11-22 09:34
閱讀 2098·2021-09-22 16:03
閱讀 2349·2019-08-29 18:37
閱讀 371·2019-08-29 16:15
閱讀 1761·2019-08-26 13:56
閱讀 853·2019-08-26 12:21
閱讀 2198·2019-08-26 12:15