最近用element来作项目,在开发的过程当中,忽然发现页面的操做和切换在数据量大的时候至关卡,后来提了个issue,在furybean解答后才知道,我每一个单元格都加了tooltip,会生成大量的节点,形成页面操做卡顿。后来将tooltip去掉,操做流畅多了。vue
可是,因为我是将页面的数据存在vuex中的,在路由切换回来的时候,发如今数据量大的时候,页面渲染得很慢,大概两三秒才能切换过来,用户体验至关很差。git
这时,我就在想,能不能让页面切换完成以后才开始渲染数据量大的组件,用户起码不会感知到路由切换的卡顿状况。github
一开始不知道怎样作,后来看到这篇blog:vue 性能优化,做者基于vue1.0作了一个指令,基本原理是利用v-if来控制组件的渲染时机。做者在回答中提到vue2.0能够用组件来作,具体的讨论能够看这里vuex
基于此,我作了个组件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() } }, },
最后,全部文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:微信