发布时间:2023-09-02
统计字数:923 字
阅读时间:5 min read
今天继续优化一下博客,首先虽然说我的博文中图片数量比较少,但是如果有个别一两个博文图片数量多,并且图片的大小比较大,那么对用户的流量来说不太友好,那么今天主要是给博文的图片加上懒加载功能。
懒加载也就是以下几个方面:
这样做有几个优点:
首先要实现该功能就需要实时地监听用户的浏览窗口,也就是当用户的可视区域有图片的时候,图片才进行加载。那么就需要用到一个极其重要的原生 api:IntersectionObserver。
IntersectionObserver
接口(从属于 Intersection Observer API)提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(root)。当一个
IntersectionObserver
对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦IntersectionObserver
被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。
MDN文档的地址: https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver
那么实现起来就超级简单了,使用该 api 对图片元素进行监听,当图片进入可视区域的时候再对图片的 src 属性进行赋值,那么浏览器就会自动进行加载了。
同时我的博客使用到了 vueuse 的框架,在 vueuse 中同样提供了该 api 的工具: useIntersectionObserver
这里附上 vueuse 文档的地址: https://vueuse.org/core/useIntersectionObserver/#useintersectionobserver
那么我在代码里面是这样实现的:
<template>
<img
class="cursor-pointer"
@click="preview"
ref="imgRef"
:src="srcComputed"
:alt="alt"
:width="width"
:height="height"
/>
</template>
<script setup lang="ts">
import { withTrailingSlash, withLeadingSlash, joinURL } from "ufo";
import { useRuntimeConfig, computed } from "#imports";
import loading from "~/assets/svg/loading.svg";
const props = defineProps({
src: {
type: String,
default: "",
},
alt: {
type: String,
default: "",
},
width: {
type: [String, Number],
default: undefined,
},
height: {
type: [String, Number],
default: undefined,
},
});
const imgRef = ref();
const isVisible = ref(false);
const { stop } = useIntersectionObserver(imgRef, ([{ isIntersecting }]) => {
if (isIntersecting) {
stop();
isVisible.value = true;
}
});
const refinedSrc = computed(() => {
if (props.src?.startsWith("/") && !props.src.startsWith("//")) {
const _base = withLeadingSlash(
withTrailingSlash(useRuntimeConfig().app.baseURL),
);
if (_base !== "/" && !props.src.startsWith(_base)) {
return joinURL(_base, props.src);
}
}
return props.src;
});
const srcComputed = computed(() => {
return isVisible.value ? refinedSrc.value : loading;
});
const preview = () => {
window.open(refinedSrc.value, "_blank");
};
</script>
首先该组件的路径是 /components/content/ProseImg.vue,主要是为了替换掉 Nuxt/Content 的原生组件,以达到自定义MDC的目的。那么主要实现懒加载的代码:
const { stop } = useIntersectionObserver(imgRef, ([{ isIntersecting }]) => {
if (isIntersecting) {
stop();
isVisible.value = true;
}
});
这部分的用法跟 vueuse 文档都差不多,当进入可视区域的时候先调用 stop 方法,也就是后续不再对该元素进行监听,然后响应式修改 isVisible 的值,通过 srcComputed 这个 computed 方法来动态赋值图片的 src 属性。
可以看到在下滑的过程中,图片是懒加载的,当出现在可视区域中才会进行请求。
懒加载是前端开发中常用的开发手段,其中又分为图片懒加载,数据懒加载和组件懒加载。通过懒加载可以有效提高我们页面的性能,优化流量和提高用户体验。
通过 IntersectionObserver 可以很轻松地做到这些功能,同时附上该 api 的兼容图。