最近用 element 来做项目,在开发的过程中,突然发现页面的操作和切换在数据量大的时候相当卡,后来提了个 issue ,在furybean解答后才知道,我每个单元格都加了tooltip,会生成大量的节点,造成页面操作卡顿。后来将tooltip去掉,操作流畅多了。
但是,由于我是将页面的数据存在vuex中的,在路由切换回来的时候,发现在数据量大的时候,页面渲染得很慢,大概两三秒才能切换过来,用户体验相当不好。
这时,我就在想,能不能让页面切换完成之后才开始渲染数据量大的组件,用户起码不会感知到路由切换的卡顿情况。
一开始不知道怎样做,后来看到这篇blog: vue 性能优化 ,作者基于vue1.0做了一个指令,基本原理是利用v-if来控制组件的渲染时机。作者在回答中提到vue2.0可以用组件来做,具体的讨论可以看 这里
基于此,我做了个组件 vue-lazy-render ,欢迎star。
<lazy-render> <my-component></my-component> </lazy-render>
<lazy-render :data="myArray" :time="300" :limit="50" track-by-data> <my-component :data="myArray"></my-component> </lazy-render>
<div class="lazy-load"> <slot v-if="show"></slot> <div v-if="!show" :class="[maskClass ? maskClass : 'lazy-load-mask']">{{tip}}</div> </div>
property | description | type | default | required |
---|---|---|---|---|
time | 多长时间后开始渲染组件 | Number | 10 | false |
immediately | 是否立即开启延迟渲染,vue-lazy-render组件会在路由切换时,会进行一次延迟渲染,如果在同一个路由中需经常对某个组件进行延迟渲染,可以将immediately由false设为true,就会马上开启一次延迟渲染 | Boolean | -- | false |
data | 如果需要延迟加载的组件是由数组渲染的,可以将数据的数据prop进vue-lazy-render组件,组件会根据配置监测数组变化,决定开启延迟加载的时机 | array | -- | false |
trackByData | 是否根据data的变化来开启延迟加载,如果设为true,需将data prop进来,并且路由切换时不会再进行延迟渲染 | Boolean | -- | false |
limit | 在数据超过多少后才开启延迟渲染,需要data和将trackByData设为true | Number | 30 | false |
maskClass | 等待渲染时的遮罩层样式 | String | -- | false |
tip | 等待渲染时的提示文字 | String | 正在渲染,请稍候 | false |
/** * 延迟渲染数据,在数据渲染完成后触发loaded事件 */ showLazy() { if ((this.data && this.data.length > this.limit) || !this.data) { // 如果数据存在并且数据的数量比限定的数量大,则开启延迟渲染 如果不是列表调用组件,也开启延迟渲染 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变为true时,组件才可以渲染,从而达到延迟渲染的目的。组件开始渲染时,会触发loaded事件。
created() { this.showLazy() }, watch: { data() { // 数据变化时重新渲染 if (this.trackByData) { this.showLazy() } }, // 路由变化,重新渲染 $route() { if (!this.trackByData) { this.showLazy() } }, // 立即重新变为true时,重新渲染 immediately() { if (this.immediately) { this.showLazy() } }, },
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见: