摘要:最近在開發(fā)一個(gè)長(zhǎng)圖文預(yù)覽項(xiàng)目,主要用在手機(jī)端瀏覽主要在微信端。大概的實(shí)現(xiàn)是首屏開始顯示接下來(lái)首屏后面的圖片就全部扔給瀏覽器去加載了。
最近在開發(fā)一個(gè)長(zhǎng)圖文預(yù)覽項(xiàng)目,主要用在手機(jī)端瀏覽(主要在微信端)。這項(xiàng)目其實(shí)就是一個(gè)手機(jī)網(wǎng)頁(yè),把數(shù)據(jù)中的文本和圖片等元素渲染出來(lái)即可。這樣的項(xiàng)目很常見,包括微信內(nèi)公眾號(hào)的文章etc.這個(gè)項(xiàng)目很簡(jiǎn)單,但非常頭疼的一個(gè)問(wèn)題是對(duì)圖片的懶加載處理。(下面討論的加載策略暫且都是針對(duì)圖片)
前置條件:假定項(xiàng)目數(shù)據(jù)是一個(gè)數(shù)組,數(shù)組元素都是圖片,并且指定了圖片在屏幕中的left和top。
我們最開始想到的處理方式是:優(yōu)先考慮首屏體驗(yàn)。
取得數(shù)據(jù)后,首屏先呈現(xiàn)Loading狀態(tài)。通過(guò)屏幕的高度H和圖片的top,得到首屏的圖片,并對(duì)其每一個(gè)圖片的onload和onerror事件綁定回調(diào)。當(dāng)回調(diào)全都執(zhí)行完成之后便將首屏Loading狀態(tài)移除,呈現(xiàn)首屏的圖片。大概的實(shí)現(xiàn)是:
firstScreenPromises = firstScreenImgs.map((img) => { return new Promise((resolve, reject) => { let image = new Image() image.src = img.imgSrc image.onload = image.onerror = resolve }) }) Promise.all(firstScreenPromises).then(data => { // 首屏開始顯示 })
接下來(lái)首屏后面的圖片就全部扔給瀏覽器去加載了。
上面首屏顯示優(yōu)化自然ok,不過(guò)對(duì)后面屏幕圖片的顯示策略自然是不太好的。于是考慮分屏加載,一屏一屏加載圖片。
// 分屏 screenBox = {} H = screen.height for (let i = 0; i < imgs.length; i += 1) { screenNum = Math.floor(imgs.top / H) screenBox[screenNum] = screenBox[screenNum] || [] screenBox[screenNum].push(imgs[i]) } indexs = Object.keys(screenBox) ----------上邊代碼塊 (X) 繼續(xù)給下一塊代碼使用——------------ loadNext() // 分屏按序加載 function loadNext() { if (!indexs.length) return screenBox[indexs[0]].map(img=>{ // 同首屏firstScreenPromises }).then(data=>{ // load完后回調(diào)該函數(shù)繼續(xù)load下一屏 indexs.shift() loadNext() }) }
上面優(yōu)化點(diǎn)在于按序分屏加載圖片,這適合用戶慢慢往下看的情況,但是會(huì)有兩個(gè)弊端。
一是:如果用戶突然猛翻到頁(yè)面較后的位置,此時(shí)如果還在加載前面某屏的圖片,那用戶需要等待。
二是:如果頁(yè)面圖片元素非常多,屏幕數(shù)很多,會(huì)消耗許多流量,也許用戶不想看到最后咧。
于是考慮控制預(yù)加載的屏幕數(shù),用戶看屏幕所時(shí)處的屏幕數(shù)為N,預(yù)加載N+1,N+2....N+M,最多預(yù)加載M屏。同時(shí)監(jiān)聽屏幕滾動(dòng),通過(guò)滾動(dòng)的高度算出用戶所處的屏幕數(shù)。
....上邊代碼塊(X)..... loadNext(0) // 初始化load首屏 window.onscroll = ()=>{ getViewScreenIndex = function() { // 滾動(dòng)監(jiān)聽求出用戶視野所處的屏幕數(shù)(若處在a,a+1,取a) return ... } loadNext(getViewScreenIndex()) } // 加載第N屏,加載完繼續(xù)加載到第N+M屏 function loadNext(N) { hasLoad = 0 function load() { if (hasLoad == M) { // 已經(jīng)加載到N+M屏,停止預(yù)加載 return } hasLoad++ if (indexs.indexOf(N) > -1) { screenBox[indexs[0]].map(img=>{ // 同首屏firstScreenPromises }).then(data=>{ // load完后回調(diào)該函數(shù)繼續(xù)load下一屏 indexs.splice(indexs.indexOf(N), 1) load() }) } else { load() } } }
最后一個(gè)優(yōu)化點(diǎn):假設(shè)正在load第1屏(接下來(lái)會(huì)預(yù)加載第2,3屏),此時(shí)屏幕滾動(dòng)到了第4屏(將會(huì)預(yù)加載第5,6屏)。此時(shí)是否還有必要繼續(xù)去加載第2,3屏?我覺得是沒必要的,用戶更有可能會(huì)繼續(xù)往后翻。所以此時(shí)我會(huì)取消掉2,3屏的預(yù)加載(當(dāng)然,如果此時(shí)正在預(yù)加載第2屏,那只會(huì)取消掉第3屏的加載)。
這一塊的代碼,加上一些細(xì)節(jié)處理,可以到我的github lazyloader看看。
總結(jié):目前能考慮到的上邊策略為的是提升用戶體驗(yàn)(預(yù)加載),同時(shí)不會(huì)去消耗太多流量(限制預(yù)加載的數(shù)目)。但我相信還會(huì)有更加優(yōu)化的策略,希望能得到高人的指點(diǎn),那就真的灰常感激啦!
同時(shí),這里邊還會(huì)遇到一些兼容上的坑。比如:此處我所用到的滾動(dòng)監(jiān)聽是window.onscroll。這個(gè)監(jiān)聽事件在不同設(shè)備上的表現(xiàn)非常不一樣,會(huì)使得這里的加載策略不一定能使所有的設(shè)備都體驗(yàn)不錯(cuò)。
android的(不確定是不是所有)window.onscroll會(huì)在手指按著屏幕拖動(dòng)時(shí)觸發(fā),以及屏幕滾動(dòng)停止的時(shí)候觸發(fā);而ios的則是只在屏幕停止?jié)L動(dòng)的時(shí)候才會(huì)觸發(fā)。這兩者,在松開手后屏幕滾動(dòng)時(shí)都不會(huì)觸發(fā)onscroll事件。
目前還沒想到比較好的兼容策略,希望有人能提供好的資料和想法借鑒借鑒,感激涕零。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/80189.html
摘要:虛擬列表的實(shí)現(xiàn)有多種方案,本文以組件為基礎(chǔ)進(jìn)行分析。常見的無(wú)限滾動(dòng)便是延遲渲染的一種實(shí)現(xiàn),而虛擬列表則是按需渲染的一種實(shí)現(xiàn)。接下來(lái),本文會(huì)簡(jiǎn)單介紹虛擬列表的一種實(shí)現(xiàn)方案。實(shí)現(xiàn)本章節(jié)將會(huì)創(chuàng)建一個(gè)組件,并結(jié)合代碼,慢慢梳理虛擬列表的實(shí)現(xiàn)。 在 列表數(shù)據(jù)的展示優(yōu)化 一文中,提到了對(duì)于列表形態(tài)的數(shù)據(jù)展示的按需渲染。這種方式是指根據(jù)容器元素的高度以及列表項(xiàng)元素的高度來(lái)顯示長(zhǎng)列表數(shù)據(jù)中的某一個(gè)部分...
摘要:商品詳情頁(yè)上拉查看詳情目錄介紹該庫(kù)介紹效果展示如何使用注意要點(diǎn)優(yōu)化問(wèn)題部分代碼邏輯參考案例該庫(kù)介紹模仿淘寶京東考拉等商品詳情頁(yè)分頁(yè)加載的效果。 商品詳情頁(yè)上拉查看詳情 目錄介紹 01.該庫(kù)介紹 02.效果展示 03.如何使用 04.注意要點(diǎn) 05.優(yōu)化問(wèn)題 06.部分代碼邏輯 07.參考案例 01.該庫(kù)介紹 模仿淘寶、京東、考拉等商品詳情頁(yè)分頁(yè)加載的UI效果??梢郧短識(shí)ecycl...
摘要:對(duì)深度學(xué)習(xí)模型而言,水就是海量的數(shù)據(jù)。就拿機(jī)器識(shí)別物體這樣的任務(wù)來(lái)說(shuō),通過(guò)數(shù)百萬(wàn)副圖片的訓(xùn)練,深度學(xué)習(xí)模型甚至可以超過(guò)人的肉眼的識(shí)別能力,這確實(shí)是人工智能在感知類問(wèn)題上重要的里程碑。關(guān)于深度學(xué)習(xí),還有一個(gè)有趣的現(xiàn)象。 說(shuō)到人工智能和機(jī)器人,上點(diǎn)兒歲數(shù)的碼農(nóng)們可能對(duì)封面這張圖有點(diǎn)印象。不明就里的朋友,可以回去補(bǔ)習(xí)一下《編輯部的故事》。我是個(gè)二手的人工智能表演藝術(shù)家:從博士畢業(yè)開始,就在MSRA...
閱讀 3218·2023-04-25 18:22
閱讀 2510·2021-11-17 09:33
閱讀 3620·2021-10-11 10:59
閱讀 3306·2021-09-22 15:50
閱讀 2939·2021-09-10 10:50
閱讀 921·2019-08-30 15:53
閱讀 508·2019-08-29 11:21
閱讀 3043·2019-08-26 13:58