懒加载是前端开发者的基本功之一。实现懒加载确定是要直接操做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绑定在一个对象里,方便操做:dom
class LazyImage { constructor(src) { this.src = src; // 图片url或base64 this.dom = null; // 承载图片的DOM元素 this.status = 'pending'; // 图片当前状态 } }
其中status表示图片资源当前的状态,有pending(未加载)、loading(加载中)、loaded(加载完成或失败)三个取值。函数
最后,咱们须要一张占位图,用于图片加载完成前占位展现。post
当网页从服务器拉取到10条帖子时,每一个帖子子组件各自把本身负责的图片和DOM对应起来,放进同一个LazyImage对象,而后push进imageList。性能
这一步有两个地方须要注意:this
1. 承载图片的DOM对象,其src/background-image值应设为占位图,真正的图片url先保存在data-src属性里,用于图片url和DOM元素“相认”;url
2. 在mounted钩子函数里直接访问this.$refs可能为空,由于此时真正的DOM渲染还没完成,能够放在this.$nextTick的回调函数里访问。spa
在父组件里监听window的scroll事件,每次触发时,先把状态不为pending的图片给filter出去,而后检查一下imageList里的每一个图片的DOM是否在当前可视范围内里,如果,则将其src/background-image替换为真正的图片url,不不不,直接替换连接不够优雅,如果原图很大,网速又不太快,图片就会像挤牙膏同样,一点一点地显露出来,使人捉急。咱们能够先new一个Image对象,预加载原图,待图片加载完成后,再把真正的url替换上去,作到无缝切换。
注意点:
1. scroll事件触发频繁,为减轻对性能的影响,能够加上节流措施,好比设定滚动距离大于必定阈值时才触发对imageList的遍历检查;
2. 在首屏加载完成后,须要手动触发一次检查,不然在不滚动的状况下首屏图片不加载。
这样就轻松实现了图片的懒加载。