在滑动列表视图中如果有网络图片需要加载直接给imag标签赋值src,会造成没有显示的item中图片也直接加载,势必浪费网络资源。
创建一个插件,让列表中的item出显的时候在加载图片从而减少网络请求。具体方法就是给img标签添加一个新的属性暂时先保存对应的url,当item滑动出现到一定值时触发事件再吧url赋值给image标签
具体代码:
import type { App, DirectiveBinding } from 'vue'
const vLazy = (observer: IntersectionObserver) => {
return {
beforeMount: (el: HTMLImageElement, binding: DirectiveBinding) => {
el.classList.add('op-lazyload')
el.dataset.lazyKey = binding.value
observer.observe(el)
},
}
}
const lazyPlugin = {
install(app: App) {
//一种方法,以异步地观察目标元素与祖先元素或与顶级视口相交时的更改。
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((item) => {
if (item.isIntersecting) {
// 开始加载图片,把 data-origin 的值放到 src
const el = item.target as HTMLImageElement
el.src = el.dataset.lazyKey as string
el.classList.remove('op-lazyload')
// 停止监听
observer.unobserve(el)
}
})
},
{
// 交叉视图的 100ps,才开始派发事件
rootMargin: '0px 0px -100px 0px',
}
)
//添加一个名字叫lazy的指令 // <img v-lazy="" />
app.directive('lazy', vLazy(observer))
},
}
export default lazyPlugin
//第二个参数是 触发这个指令时要做的逻辑,可以在一些生命周期函数中执行内容,
//本文是在beforeMount函数添加逻辑
// export declare interface ObjectDirective<T = any, V = any> {
// created?: DirectiveHook<T, null, V>;
// beforeMount?: DirectiveHook<T, null, V>;
// mounted?: DirectiveHook<T, null, V>;
// beforeUpdate?: DirectiveHook<T, VNode<any, T>, V>;
// updated?: DirectiveHook<T, VNode<any, T>, V>;
// beforeUnmount?: DirectiveHook<T, null, V>;
// unmounted?: DirectiveHook<T, null, V>;
// getSSRProps?: SSRDirectiveHook;
// deep?: boolean;
// }
使用也很简单,第一步先添加插件:
app.use(lazyPlugin)
然后在图片标签处代替rsc
<img class="item__poster" v-lazy="data.postUrl" />