您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Vue.js如何優化無限滾動列表的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
問題
大家都知道,Web 頁面修改 DOM 是開銷較大的操作,相比其他操作要慢很多。這是為什么呢?因為每次 DOM 修改,瀏覽器往往需要重新計算元素布局,再重新渲染。也就是所謂的重排(reflow)和重繪(repaint)。尤其是在頁面包含大量元素和復雜布局的情況下,性能會受到影響。那對用戶有什么實際的影響呢?
一個常見的場景是大數據量的列表渲染。通常表現為可無限滾動的無序列表或者表格,當數據很多時,頁面會出現明顯的滾動卡頓,嚴重影響了用戶體驗。怎么解決呢?
解決方案
既然問題的根源是 DOM 元素太多,那就想辦法限制元素數量。
限制列表對用戶可見的元素數量。我們把可見區域稱為 ViewPort
當列表滾動時,列表種的其他元素怎么由不可見變為可見?
監聽列表容器元素的滾動事件,當列表里的元素進入可視區域,則添加到DOM中
問題是如果一直這么滾下去,列表會越來越大。所以需要在列表元素離開 ViewPort 的時候從DOM中移除
問題又來了,由于 ViewPort 剛好是一屏的大小,滾動的時候元素還沒來得及渲染,會出現一段時間的空白。解決辦法就是上下增加一部分數據渲染。
無限滾動的性能優化方案基本思路就是這樣。
在實際項目中,我們可能不需要自己從頭實現一個無限滾動列表組件,Vue.js 就有一個現成的輪子:vue-virtual-scroller。
在項目中安裝這個插件:
$ npm install -D vue-virtual-scroller
項目入口文件 main.js 引入這個插件:
import "vue-virtual-scroller/dist/vue-virtual-scroller.css"; import Vue from "vue"; import VueVirtualScroller from "vue-virtual-scroller"; Vue.use(VueVirtualScroller);
案例一:VirtualList
我們來看一個簡單的例子,用vue-virtual-scroller渲染一個包含大量數據的列表。 先用JSON-Generator 生成 5000 條數據的 JSON 對象,并保存到 data.json 文件。可以用下面的規則:
[ '{{repeat(5000)}}', { _id: '{{objectId()}}', age: '{{integer(20, 40)}}', name: '{{firstName()}} {{surname()}}', company: '{{company().toUpperCase()}}' } ]
新建一個 VirtualList.vue 文件,引入data.json,并將它賦值給組件的items屬性。然后套一個 <virtual-scroller>組件:
VirtualList.vue:
<template> <virtual-scroller :items="items" item-height="40" content-tag="ul"> <template slot-scope="props"> <li :key="props.itemKey">{{props.item.name}}</li> </template> </virtual-scroller> </template> <script> import items from "./data.json"; export default { data: () => ({ items }) }; </script>
virtual-scroller 組件必須設置 item-height 。另外,由于我們要創建一個列表,可以設置content-tag="ul",表示內容渲染成 <ul>標簽。
vue-virtual-scroller 支持使用 scoped slots,增加了內容渲染的靈活性。通過使用slot-scope="props",我們可以訪問 vue-virtual-scroller 暴露的數據。
props 有一個itemKey屬性,出于性能考慮,我們應該在內容部分的根元素上綁定 :key="props.itemKey"。然后我們就可以通過 props.item 拿到 JSON 里的原始數據了。
如果你要給列表設置樣式,可以給 virtual-scroller 設置 class屬性:
<template> <virtual-scroller class="virtual-list" ...></virtual-scroller> </template> <style> .virtual-list ul { list-style: none; } </style>
或者也可以用scoped 樣式,用 /deep/選擇器:
<style scoped> .virtual-list /deep/ ul { list-style: none; } </style>
案例二: VirtualTable
類似 VirtualList,我們再看一個表格組件VirtualTable: VirtualTable.vue:
<template> <virtual-scroller :items="items" item-height="40" content-tag="table"> <template slot-scope="props"> <tr :key="props.itemKey"> <td>{{props.item.age}}</td> <td>{{props.item.name}}</td> <td>{{props.item.company}}</td> </tr> </template> </virtual-scroller> </template> <script> import items from "./data.json"; export default { data: () => ({ items }) }; </script>
這里有個小問題,我們需要增加一個 <thead>標簽,用于顯示列名: Age, Name 和 Company
幸好 virtual-scroller 支持 slot,可以定制各部分內容:
<main> <slot name="before-container"></slot> <container> <slot name="before-content"></slot> <content> <!-- Your items here --> </content> <slot name="after-content"></slot> </container> <slot name="after-container"></slot> </main>
這些 slot 都可以放置自定義內容。container 會被 container-tag 屬性值替換,默認是div,content 被 content-tag 值替換。
這里用 before-content slot 加一個thead 就行了:
<template> <virtual-scroller :items="items" item-height="40" container-tag="table" content-tag="tbody" > <thead slot="before-content"> <tr> <td>Age</td> <td>Name</td> <td>Company</td> </tr> </thead> <template slot-scope="props"> <tr :key="props.itemKey"> <td>{{props.item.age}}</td> <td>{{props.item.name}}</td> <td>{{props.item.company}}</td> </tr> </template> </virtual-scroller> </template>
請注意,我們把content-tag="table" 改成了content-tag="tbody",因為我們設置了container-tag="table",這是為了構造table 標簽的常規結構。
如果要加一個 tfoot,應該知道怎么做了吧。
感謝各位的閱讀!關于“Vue.js如何優化無限滾動列表”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。