最近用element來做項目大诸,在開發(fā)的過程中捅厂,突然發(fā)現(xiàn)頁面的操作和切換在數(shù)據(jù)量大的時候相當卡,后來提了個issue,在furybean解答后才知道底挫,我每個單元格都加了tooltip恒傻,會生成大量的節(jié)點脸侥,造成頁面操作卡頓建邓。后來將tooltip去掉,操作流暢多了睁枕。
但是官边,由于我是將頁面的數(shù)據(jù)存在vuex中的,在路由切換回來的時候外遇,發(fā)現(xiàn)在數(shù)據(jù)量大的時候注簿,頁面渲染得很慢,大概兩三秒才能切換過來跳仿,用戶體驗相當不好诡渴。
這時,我就在想菲语,能不能讓頁面切換完成之后才開始渲染數(shù)據(jù)量大的組件妄辩,用戶起碼不會感知到路由切換的卡頓情況。
一開始不知道怎樣做山上,后來看到這篇blog:vue 性能優(yōu)化,作者基于vue1.0做了一個指令眼耀,基本原理是利用v-if來控制組件的渲染時機。作者在回答中提到vue2.0可以用組件來做佩憾,具體的討論可以看這里
基于此哮伟,我做了個組件vue-lazy-render干花,歡迎star。
基本功能
- 延遲加載組件
- 控制延遲加載的時間
- 可以監(jiān)控數(shù)組的變化和設定數(shù)據(jù)量來決定是否開啟延遲加載
基本用法
默認
<lazy-render>
<my-component></my-component>
</lazy-render>
trackByData
<lazy-render :data="myArray" :time="300" :limit="50" track-by-data>
<my-component :data="myArray"></my-component>
</lazy-render>
源碼解釋
template
<div class="lazy-load">
<slot v-if="show"></slot>
<div v-if="!show" :class="[maskClass ? maskClass : 'lazy-load-mask']">{{tip}}</div>
</div>
props
property | description | type | default | required |
---|---|---|---|---|
time | 多長時間后開始渲染組件 | Number | 10 | false |
immediately | 是否立即開啟延遲渲染,vue-lazy-render組件會在路由切換時,會進行一次延遲渲染,如果在同一個路由中需經常對某個組件進行延遲渲染,可以將immediately由false設為true,就會馬上開啟一次延遲渲染 | Boolean | -- | false |
data | 如果需要延遲加載的組件是由數(shù)組渲染的,可以將數(shù)據(jù)的數(shù)據(jù)prop進vue-lazy-render組件,組件會根據(jù)配置監(jiān)測數(shù)組變化,決定開啟延遲加載的時機 | array | -- | false |
trackByData | 是否根據(jù)data的變化來開啟延遲加載,如果設為true,需將data prop進來,并且路由切換時不會再進行延遲渲染 | Boolean | -- | false |
limit | 在數(shù)據(jù)超過多少后才開啟延遲渲染,需要data和將trackByData設為true | Number | 30 | false |
maskClass | 等待渲染時的遮罩層樣式 | String | -- | false |
tip | 等待渲染時的提示文字 | String | 正在渲染,請稍候 | false |
methods
/**
* 延遲渲染數(shù)據(jù),在數(shù)據(jù)渲染完成后觸發(fā)loaded事件
*/
showLazy() {
if ((this.data && this.data.length > this.limit) || !this.data) { // 如果數(shù)據(jù)存在并且數(shù)據(jù)的數(shù)量比限定的數(shù)量大,則開啟延遲渲染 如果不是列表調用組件,也開啟延遲渲染
this.syncLoader()
} else { // 其他情況,不開啟延遲渲染
this.show = true
this.$emit('loaded')
}
},
/**
* 延遲渲染
*/
syncLoader() {
this.show = false
setTimeout(() => {
this.show = true
this.$emit('loaded')
},this.time)
}
定義的方法很簡單楞黄,在data定義的show初始值為false池凄,在需要延遲加載時,會用一個setTimeout來將show設為true鬼廓,當show變?yōu)閠rue時修赞,組件才可以渲染,從而達到延遲渲染的目的桑阶。組件開始渲染時柏副,會觸發(fā)loaded事件。
調用
created() {
this.showLazy()
},
watch: {
data() { // 數(shù)據(jù)變化時重新渲染
if (this.trackByData) {
this.showLazy()
}
},
// 路由變化,重新渲染
$route() {
if (!this.trackByData) {
this.showLazy()
}
},
// 立即重新變?yōu)閠rue時,重新渲染
immediately() {
if (this.immediately) {
this.showLazy()
}
},
},
- 在頁面進入時蚣录,開啟
- 如果不是track-by-data模式割择,則每次路由切換時,開啟
- 如果是track-by-data模式萎河,則數(shù)組變化時荔泳,開啟。由于我的頁面中虐杯,有些表格是在彈層中展示的玛歌,同一個組件,可能每次打開彈層時擎椰,數(shù)據(jù)都不一樣支子,一開始打算用這種方法來實現(xiàn)延遲的,后來加了immediately达舒,感覺這個track-by-data模式完全沒有意義了值朋,用了反應會造成不必要的重新渲染。
- 當immediately由false變?yōu)閠rue時巩搏,開啟
最后昨登,所有文章都會同步發(fā)送到微信公眾號上,歡迎關注,歡迎提意見: