当撰写显示多个(例如:展示数百笔广告)图片的网页时,效能与用户体验主要有以下课题:
如何节省不必要的加载(不加载使用者还没看到的)批次载入图片(每次载入100笔,看完再加载另外100笔)例如公司开发了一只产品,其功能让使用者选择多个品牌(例:肯德基,家乐福...),按下搜寻后显示我们从资料查询到这些厂商的广告图片,少则数十,多则数千。
这时如果我们可以每次载入100笔,并且只在使用者"将要"看到某张图片时或者某张图片"已经"出现在使用者的画面上,才向server请求该图片,如此一来便可以大幅提升网页渲染的速度,同时节省client与server的负担,关于这一点,可以请大家一同观赏这篇好文。
好文共赏
基于上文範例,我们可以进一步思考,是不是可以利用IntersectionObserver
的特性,达到我们的第2个目标:在使用者看完目前的图片时,载入后续的图片。
因此解决方法的关键点在于当IntersectionObserver
监听到目前最后一笔图片出现在萤幕上时,除了要向server请求这张图片外,还要向server请求并渲染后续的图片。
为了达到这样的目标,我们可以设定每次载入100笔图片,并在生成每张图片时为它添加data-id
属性,值为它出现的顺序(1,2,3,...),如此一来当IntersectionObserver
监听图片的data-id
值若为100的倍数,请求这张图片同时调用请求后续图片的函式。
this._observer = new IntersectionObserver((entries, observer) => { const ins = this; entries.forEach(e=>{ if(e.isIntersecting){ const container = e.target; //图片载入显示时加一点特效 container.classList.add("fadeIn"); const img = container.querySelector("img"); img.setAttribute("src", img.dataset.url); img.removeAttribute("data-url"); observer.unobserve(container); //当图片的data-id值为100的倍数时,呼叫向伺服器请求并渲染图片的方法 //第二个条件可以选用,让你控制每页图片的最大数量 if (container.dataset.id % 100 === 0 && container.dataset.id <= 400) { ins.generateImg(100); } } }); });
如此一来便可以达到我们设定的两个目标,只载入使用者萤幕上的图片以及批次载入图片,而这一切都可以靠运用IntersectionObserver
达成,以下是我在codePen上对该方法的实践,提供大家参考。
点我看示範