Vue实现懒加载的基本思路

懒加载是前端开发者的基本功之一。实现懒加载肯定是要直接操作DOM的,这个没得跑,但我们可以想办法让流程尽可能优雅些。

基本结构

父组件是列表容器,子组件是列表中的项,如卡片、帖子等,承载图片的DOM对象由子组件直接管理。

<div class="list-container">
    <item v-for="post in postlist" :key="post.id" :images="post.images" :text="post.text"></item>
</div>

实现思路

准备工作

首先,我们需要一个父子组件都能访问和操作的数组imageList,可以考虑放在一个专门的模块里,父子组件各自import。

然后,我们定义一个名叫LazyImage的类,用于把图片的url和DOM绑定在一个对象里,方便操作:

class LazyImage {
    constructor(src) {
        this.src = src;           // 图片url或base64
        this.dom = null;          // 承载图片的DOM元素
        this.status = 'pending';  // 图片当前状态
    }
}

其中status表示图片资源当前的状态,有pending(未加载)、loading(加载中)、loaded(加载完成或失败)三个取值。

最后,我们需要一张占位图,用于图片加载完成前占位展示。

步骤1

当网页从服务器拉取到10条帖子时,每个帖子子组件各自把自己负责的图片和DOM对应起来,放进同一个LazyImage对象,然后push进imageList

这一步有两个地方需要注意:

1. 承载图片的DOM对象,其src/background-image值应设为占位图,真正的图片url先保存在data-src属性里,用于图片url和DOM元素“相认”;

2. 在mounted钩子函数里直接访问this.$refs可能为空,因为此时真正的DOM渲染还没完成,可以放在this.$nextTick的回调函数里访问。

步骤2

在父组件里监听window的scroll事件,每次触发时,先把状态不为pending的图片给filter出去,然后检查一下imageList里的每个图片的DOM是否在当前可视范围内里,若是,则将其src/background-image替换为真正的图片url,不不不,直接替换链接不够优雅,若是原图很大,网速又不太快,图片就会像挤牙膏一样,一点一点地显露出来,令人捉急。我们可以先new一个Image对象,预加载原图,待图片加载完成后,再把真正的url替换上去,做到无缝切换。

注意点:

1. scroll事件触发频繁,为减轻对性能的影响,可以加上节流措施,比如设定滚动距离大于一定阈值时才触发对imageList的遍历检查;

2. 在首屏加载完成后,需要手动触发一次检查,否则在不滚动的情况下首屏图片不加载。

 

这样就轻松实现了图片的懒加载。

posted on 2018-08-17 23:36  大唐西域都护  阅读(22708)  评论(0编辑  收藏  举报

导航